diff --git a/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.lfm b/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.lfm index b3c9548ca..396a0492e 100644 --- a/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.lfm +++ b/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.lfm @@ -29,10 +29,8 @@ object JvChartDemoForm: TJvChartDemoForm Options.XOrigin = 0 Options.YOrigin = 0 Options.XStartOffset = 60 - Options.YStartOffset = 42 Options.PrimaryYAxis.YMax = 20 Options.PrimaryYAxis.YMin = 0 - Options.PrimaryYAxis.YDivisions = 20 Options.PrimaryYAxis.YLegendDecimalPlaces = 1 Options.SecondaryYAxis.YMax = 140 Options.SecondaryYAxis.YMin = 0 @@ -41,8 +39,6 @@ object JvChartDemoForm: TJvChartDemoForm Options.MouseDragObjects = False Options.Legend = clChartLegendBelow Options.LegendRowCount = 1 - Options.PenLineWidth = 2 - Options.AxisLineWidth = 3 Options.XValueCount = 20 Options.HeaderFont.Color = clWindowText Options.LegendFont.Color = clWindowText @@ -50,8 +46,6 @@ object JvChartDemoForm: TJvChartDemoForm Options.AxisTitleFont.Height = -16 Options.AxisTitleFont.Orientation = 900 Options.AxisTitleFont.Style = [fsBold] - Options.PaperColor = clWhite - Options.AxisLineColor = clBlack Options.CursorColor = clBlack Options.CursorStyle = psDot OnBeginFloatingMarkerDrag = ChartBeginFloatingMarkerDrag @@ -578,9 +572,9 @@ object JvChartDemoForm: TJvChartDemoForm Caption = 'Use Positive and Negative Demo Values (-20..+20)' OnClick = MenuNegValueTestClick end - object MenuSecondaryAxisMode: TMenuItem + object mnuSecondaryAxisMode: TMenuItem Caption = '&Plot Markers+Values using Alternate Scale (0-120%)' - OnClick = MenuSecondaryAxisModeClick + OnClick = mnuSecondaryAxisModeClick end object N4: TMenuItem Caption = '-' diff --git a/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.pas b/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.pas index be9e2ff0c..65e95e6fa 100644 --- a/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.pas +++ b/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.pas @@ -37,9 +37,9 @@ unit JvChartDemoFm; interface uses - Windows, SysUtils, Messages, Classes, Graphics, Controls, + SysUtils, Classes, Graphics, Controls, Menus, Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, Spin, PrintersDlgs, - JvChart, JvComponent, JvExControls, StatsClasses, Menus; + JvChart, StatsClasses; type @@ -109,7 +109,7 @@ type PrintOptions1: TMenuItem; PrinterSetupDialog1: TPrinterSetupDialog; PrintDialog1: TPrintDialog; - MenuSecondaryAxisMode: TMenuItem; + mnuSecondaryAxisMode: TMenuItem; MenuNegValueTest: TMenuItem; SpeedButtonTestMouseOver: TSpeedButton; NewFeaturesfor20071: TMenuItem; @@ -151,7 +151,7 @@ type procedure FormDestroy(Sender: TObject); procedure PrintOptions1Click(Sender: TObject); - procedure MenuSecondaryAxisModeClick(Sender: TObject); + procedure mnuSecondaryAxisModeClick(Sender: TObject); procedure ListBox1Click(Sender: TObject); procedure ListBox1DblClick(Sender: TObject); @@ -203,6 +203,7 @@ var implementation uses + LCLIntf, // OpenURL LCLType, // MB_OK Math, // Math:NaN handling, function isNan in D6 and higher. JvPenEditor; @@ -289,7 +290,7 @@ begin // if Chart.Options.XAxisDateTimeMode was also set. Chart.Options.XLegends.Add(FormatDateTime('hh:nn:ss', Fds)); - if MenuSecondaryAxisMode.Checked then + if mnuSecondaryAxisMode.Checked then begin if I = 1 then Chart.Data.Value[3, I] := 100 @@ -461,7 +462,7 @@ begin PenStyle[1] := psDash; PenStyle[2] := psDot; - if MenuSecondaryAxisMode.Checked then + if mnuSecondaryAxisMode.Checked then begin PenCount := 4; // Add a pen for right side demo. SecondaryYAxis.YMax := 140; // Example shows Q/A percentage. Experimental results @@ -488,14 +489,14 @@ begin PenLegends.Add('HgT'); PenLegends.Add('Hg0'); PenLegends.Add('Hg2+'); - if MenuSecondaryAxisMode.Checked then + if mnuSecondaryAxisMode.Checked then PenLegends.Add('Quality%'); PenUnit.Clear; PenUnit.Add('ug/m3'); PenUnit.Add('ug/m3'); PenUnit.Add('ug/m3'); - if MenuSecondaryAxisMode.Checked then + if mnuSecondaryAxisMode.Checked then PenUnit.Add('%'); // Optional Pen in percentage scale. //ShowLegend := TRUE; @@ -586,8 +587,8 @@ end; procedure TJvChartDemoForm.SpinEdit1Change(Sender: TObject); begin // Chart.Options.PrimaryYAxis.YPixelGap := SpinEdit1.Value; -// Chart.Options.YStartOffset := SpinEdit1.Value; - Chart.Options.XStartOffset := SpinEdit1.Value; + Chart.Options.YStartOffset := SpinEdit1.Value; +// Chart.Options.XStartOffset := SpinEdit1.Value; // Chart.Options.ColorScheme := SpinEdit1.Value; // Chart.PlotGraph; end; @@ -622,7 +623,8 @@ end; procedure TJvChartDemoForm.Panel2DblClick(Sender: TObject); begin - ShellExecute(HWND(nil), 'show', 'http://jvcl.delphi-jedi.org/', nil, nil, SW_SHOW); + OpenURL('http://jvcl.delphi-jedi.org/'); +// ShellExecute(HWND(nil), 'show', 'http://jvcl.delphi-jedi.org/', nil, nil, SW_SHOW); end; procedure TJvChartDemoForm.ShowgapinLineChart1Click(Sender: TObject); @@ -679,7 +681,7 @@ var w: Integer; begin s := InputBox('Set Axis Linewidth', 'Value:', IntToStr(Chart.Options.AxisLineWidth)); - if TryStrToInt(s, w) and (w > 0) then + if TryStrToInt(s, w) and (w >= 0) then Chart.Options.AxisLineWidth := w else MessageDlg('No valid number for axis linewidth', mtError, [mbOk], 0); @@ -889,11 +891,11 @@ begin PrinterSetupDialog1.Execute; end; -procedure TJvChartDemoForm.MenuSecondaryAxisModeClick(Sender: TObject); +procedure TJvChartDemoForm.mnuSecondaryAxisModeClick(Sender: TObject); begin - MenuSecondaryAxisMode.Checked := not MenuSecondaryAxisMode.Checked; + mnuSecondaryAxisMode.Checked := not mnuSecondaryAxisMode.Checked; - if MenuSecondaryAxisMode.Checked then + if mnuSecondaryAxisMode.Checked then begin ButtonLine.Down := true; ButtonLineClick(Sender); diff --git a/components/jvcllaz/examples/JvChartDemo/jvpeneditor.lfm b/components/jvcllaz/examples/JvChartDemo/jvpeneditor.lfm index 10d22ac59..8e882e78d 100644 --- a/components/jvcllaz/examples/JvChartDemo/jvpeneditor.lfm +++ b/components/jvcllaz/examples/JvChartDemo/jvpeneditor.lfm @@ -1,10 +1,11 @@ object PenEditorForm: TPenEditorForm Left = 347 - Height = 291 + Height = 302 Top = 128 Width = 505 + BorderStyle = bsDialog Caption = 'PenEditorForm' - ClientHeight = 291 + ClientHeight = 302 ClientWidth = 505 OnCreate = FormCreate OnDestroy = FormDestroy @@ -13,7 +14,7 @@ object PenEditorForm: TPenEditorForm object btnPenColor: TButton Left = 232 Height = 25 - Top = 216 + Top = 232 Width = 64 AutoSize = True Caption = 'Color...' @@ -22,7 +23,7 @@ object PenEditorForm: TPenEditorForm end object rgPenStyle: TRadioGroup Left = 224 - Height = 160 + Height = 168 Top = 40 Width = 121 AutoFill = True @@ -34,7 +35,7 @@ object PenEditorForm: TPenEditorForm ChildSizing.ShrinkVertical = crsScaleChilds ChildSizing.Layout = cclLeftToRightThenTopToBottom ChildSizing.ControlsPerLine = 1 - ClientHeight = 140 + ClientHeight = 148 ClientWidth = 117 Items.Strings = ( 'Solid' @@ -50,7 +51,7 @@ object PenEditorForm: TPenEditorForm object ButtonPanel1: TButtonPanel Left = 6 Height = 34 - Top = 251 + Top = 262 Width = 493 OKButton.Name = 'OKButton' OKButton.DefaultCaption = True @@ -65,7 +66,7 @@ object PenEditorForm: TPenEditorForm end object lbPens: TListBox Left = 8 - Height = 200 + Height = 216 Top = 8 Width = 200 ItemHeight = 0 @@ -77,7 +78,7 @@ object PenEditorForm: TPenEditorForm object btnAdd: TButton Left = 11 Height = 25 - Top = 216 + Top = 232 Width = 48 AutoSize = True Caption = 'Add' @@ -87,7 +88,7 @@ object PenEditorForm: TPenEditorForm object btnDelete: TButton Left = 64 Height = 25 - Top = 216 + Top = 232 Width = 59 AutoSize = True Caption = 'Delete' @@ -105,7 +106,7 @@ object PenEditorForm: TPenEditorForm object btnClear: TButton Left = 128 Height = 25 - Top = 216 + Top = 232 Width = 53 AutoSize = True Caption = 'Clear' @@ -123,12 +124,12 @@ object PenEditorForm: TPenEditorForm object ColorSample: TShape Left = 304 Height = 25 - Top = 216 + Top = 232 Width = 25 end object rgMarker: TRadioGroup Left = 376 - Height = 160 + Height = 136 Top = 40 Width = 112 AutoFill = True @@ -140,7 +141,7 @@ object PenEditorForm: TPenEditorForm ChildSizing.ShrinkVertical = crsScaleChilds ChildSizing.Layout = cclLeftToRightThenTopToBottom ChildSizing.ControlsPerLine = 1 - ClientHeight = 140 + ClientHeight = 116 ClientWidth = 108 Items.Strings = ( 'None' @@ -152,6 +153,29 @@ object PenEditorForm: TPenEditorForm OnClick = rgMarkerClick TabOrder = 8 end + object rgAxis: TRadioGroup + Left = 376 + Height = 64 + Top = 192 + Width = 113 + AutoFill = True + Caption = 'y Axis' + ChildSizing.LeftRightSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 1 + ClientHeight = 44 + ClientWidth = 109 + Items.Strings = ( + 'Primary' + 'Secondary' + ) + OnClick = rgAxisClick + TabOrder = 9 + end object ColorDialog: TColorDialog Color = clBlack CustomColors.Strings = ( diff --git a/components/jvcllaz/examples/JvChartDemo/jvpeneditor.pas b/components/jvcllaz/examples/JvChartDemo/jvpeneditor.pas index cf94804fc..cbb6823bc 100644 --- a/components/jvcllaz/examples/JvChartDemo/jvpeneditor.pas +++ b/components/jvcllaz/examples/JvChartDemo/jvpeneditor.pas @@ -15,6 +15,7 @@ type Color: TColor; Style: TPenStyle; Marker: TJvChartPenMarkerKind; + SecondaryAxis: Boolean; end; { TPenEditorForm } @@ -29,6 +30,7 @@ type edPenLegend: TEdit; lblLegend: TLabel; lbPens: TListBox; + rgAxis: TRadioGroup; rgMarker: TRadioGroup; rgPenStyle: TRadioGroup; ColorSample: TShape; @@ -42,6 +44,7 @@ type procedure lbPensDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState); procedure lbPensSelectionChange(Sender: TObject; User: boolean); + procedure rgAxisClick(Sender: TObject); procedure rgMarkerClick(Sender: TObject); procedure rgPenStyleClick(Sender: TObject); private @@ -62,7 +65,7 @@ implementation {$R *.lfm} uses - LCLType; + Math, LCLType; { TPenEditorForm } @@ -94,6 +97,7 @@ begin pen.Style := psSolid; pen.Color := clBlack; pen.Marker := pmkNone; + pen.SecondaryAxis := false; FPens.Add(pen); lbPens.Items.Add(''); end; @@ -141,6 +145,7 @@ begin pen.Style := TPenStyle(rgPenStyle.ItemIndex); pen.Marker := TJvChartPenMarkerKind(rgMarker.ItemIndex); pen.Color := ColorSample.Brush.Color; + pen.SecondaryAxis := rgAxis.ItemIndex = 1; end; procedure TPenEditorForm.edPenLegendEditingDone(Sender: TObject); @@ -257,21 +262,34 @@ begin exit; pen := TPenObj(FPens[AIndex]); + edPenLegend.Text := pen.Legend; if pen.Style = psClear then rgPenStyle.ItemIndex := rgPenStyle.Items.Count-1 else rgPenStyle.ItemIndex := ord(pen.Style); rgMarker.ItemIndex := ord(pen.Marker); + rgAxis.ItemIndex := IfThen(pen.SecondaryAxis, 1, 0); ColorSample.Brush.Color := pen.Color; edPenLegend.Enabled := true; rgPenStyle.Enabled := true; rgMarker.Enabled := true; + rgAxis.Enabled := true; btnPenColor.Enabled := true; ColorSample.Visible := true; end; +procedure TPenEditorForm.rgAxisClick(Sender: TObject); +var + pen: TPenObj; +begin + pen := GetCurrentPen; + if pen = nil then + exit; + pen.SecondaryAxis := rgAxis.ItemIndex = 1; +end; + procedure TPenEditorForm.rgMarkerClick(Sender: TObject); var pen: TPenObj; @@ -314,6 +332,7 @@ begin pen.Color := AChart.Options.PenColor[i]; pen.Style := AChart.Options.PenStyle[i]; pen.Marker := AChart.Options.PenMarkerKind[i]; + pen.SecondaryAxis := AChart.Options.PenSecondaryAxisFlag[i];; FPens.Add(pen); lbPens.Items.Add(''); end; @@ -321,6 +340,7 @@ begin edPenLegend.Enabled := false; rgPenStyle.Enabled := false; rgMarker.Enabled := false; + rgAxis.Enabled := false; btnPenColor.Enabled := false; ColorSample.Visible := false; end; diff --git a/components/jvcllaz/examples/JvChartDemo/statsclasses.pas b/components/jvcllaz/examples/JvChartDemo/statsclasses.pas index 905955210..82e832f79 100644 --- a/components/jvcllaz/examples/JvChartDemo/statsclasses.pas +++ b/components/jvcllaz/examples/JvChartDemo/statsclasses.pas @@ -33,55 +33,45 @@ Known Issues: unit StatsClasses; - interface - type -TStatArray = class + TStatArray = class protected //FFirst:Boolean; - FGrows:Boolean; // false=rolling average (circular buffer mode), true=average or sd of any number of samples (array grows without limit) - FValues:Array of Double; - FLength, // Array absolute size (may still be no data even if this is >0) - FIndex, // Where will the next sample be stored into the array? - FCount: // How many valid samples are in the array right now? - Integer; - - - procedure SetLen(aLength:Integer); - - + FGrows: Boolean; // false=rolling average (circular buffer mode), true=average or sd of any number of samples (array grows without limit) + FValues: Array of Double; + FLength: Integer; // Array absolute size (may still be no data even if this is >0) + FIndex: Integer; // Where will the next sample be stored into the array? + FCount: Integer; // How many valid samples are in the array right now? + procedure SetLen(aLength:Integer); public - procedure AddValue(aValue:Double); - - function Average:Double; - - function StandardDeviation:Double; - - property Grows:Boolean read FGrows write FGrows; // false=rolling average, true=average ALL samples (grows to fit) - - property Length:Integer read FLength write SetLen; - property Count:Integer read FCount; - //property First:Boolean read FFirst; - - procedure Reset; // Clear everything! - constructor Create; overload; constructor Create(initialLength:Integer); overload; destructor Destroy; override; + + procedure AddValue(aValue:Double); + function Average:Double; + function StandardDeviation:Double; + + property Grows:Boolean read FGrows write FGrows; // false=rolling average, true=average ALL samples (grows to fit) + property Length:Integer read FLength write SetLen; + property Count:Integer read FCount; + //property First:Boolean read FFirst; + procedure Reset; // Clear everything! end; + implementation -uses //Windows, // OutputDebugString - SysUtils, // FloatToStr - Math; // VCL's statistics routines. StdDev, etc. +uses + SysUtils, // FloatToStr + Math; // VCL's statistics routines. StdDev, etc. // Begin Rolling Average -constructor TStatArray.Create; // overload; +constructor TStatArray.Create; // overload; begin //FFirst := true; FLength := 0; @@ -123,24 +113,24 @@ begin end; -function TStatArray.Average:Double; +function TStatArray.Average:Double; var - last,i:Integer; - sum:Double; + last,i:Integer; + sum:Double; begin - if FCount <= 0 then begin + if FCount <= 0 then begin result := 0; - end else begin + end else begin sum := 0; if (FCount>FLength) then - last :=FLength-1 + last :=FLength-1 else - last :=FCount-1; + last :=FCount-1; for i := 0 to last do begin - sum := sum + FValues[i]; + sum := sum + FValues[i]; end; result := sum / (last+1); - end; + end; end; function TStatArray.StandardDeviation:Double; diff --git a/components/jvcllaz/run/JvCustomControls/jvchart.pas b/components/jvcllaz/run/JvCustomControls/jvchart.pas index 15c5e2373..39e3abcd5 100644 --- a/components/jvcllaz/run/JvCustomControls/jvchart.pas +++ b/components/jvcllaz/run/JvCustomControls/jvchart.pas @@ -98,7 +98,7 @@ unit JvChart; {$MODE OBJFPC}{$H+} {$DEFINE TJVCHART_ARRAY_OF_ARRAY} -//{$I jvcl.inc} +{.$DEFINE TEXT_BOX} interface @@ -112,8 +112,8 @@ const JvDefaultHintColor = TColor($00DDFBFA); JvDefaultAvgLineColor = TColor($00EEDDDD); - JvDefaultDivisionLineColor = clLtGray; //NEW! - JvDefaultShadowColor = clDkGray; //NEW! + JvDefaultDivisionLineColor = clLtGray; + JvDefaultShadowColor = clDkGray; JvDefaultPaperColor = clWhite; JvDefaultYLegends = 20; @@ -749,12 +749,13 @@ type procedure MyYHeader(ACanvas: TCanvas; StrText: string); // NEW procedure MyHeaderFont(ACanvas: TCanvas); procedure MyAxisFont(ACanvas: TCanvas); + procedure MyAxisTitleFont(ACanvas: TCanvas; Vertical: Boolean); procedure MySmallGraphFont(ACanvas: TCanvas); function MyTextHeight(ACanvas: TCanvas; StrText: string): Longint; { TEXTOUT stuff } procedure MyRightTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string); // RIGHT TEXT procedure MyCenterTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string); // CENTER TEXT - procedure MyLeftTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string); // LEFT ALIGN TEXT + procedure MyLeftTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string; Vertical: Boolean = false); // LEFT ALIGN TEXT // Use HintColor: procedure MyLeftTextOutHint(ACanvas: TCanvas; X, Y: Integer; const AText: string); @@ -808,6 +809,7 @@ type procedure GraphYAxis; procedure GraphYAxisDivisionMarkers; procedure GraphXAxisDivisionMarkers; // new. + function CalcXAxisTextHeight: Integer; // calculate height of x axis labels and title; procedure CalcYEnd; // Determine where the below-the bottom axis area starts function GetChartCanvas(isFloating:Boolean): TCanvas; // Get Picture.Bitmap Canvas. @@ -987,6 +989,9 @@ const DEFAULT_VALUE_COUNT = 100; // By Default TJvChartData holds 100 values per pen. Grows autofragellisticexpialidociously. :-) + X_TITLE_LABEL_DISTANCE = 4; + TITLE_MARGIN = 4; + // NEW 2007: // HELPER FUNCTIONS - NEW 2007 @@ -1868,7 +1873,6 @@ begin FLegendFont := TFont.Create; FAxisFont := TFont.Create; FAxisTitleFont := TFont.Create; - FAxisTitleFont.Orientation := 900; //FShowLegend := True; FMouseEdit := True; @@ -3785,11 +3789,11 @@ begin { Enough local functions for ya? -WP } begin MyHeaderFont(ACanvas); // nOldY := Options.YStartOffset; - nMaxTextHeight := CanvasMaxTextHeight(ACanvas) + 8; + nMaxTextHeight := CanvasMaxTextHeight(ACanvas) + 2 * TITLE_MARGIN; // Bump bottom margins if the fonts don't fit! - if Options.YStartOffset < 2 * nMaxTextHeight then + if Options.YStartOffset < nMaxTextHeight then begin - Options.YStartOffset := nMaxTextHeight * 2; + Options.YStartOffset := nMaxTextHeight; //Options.YEnd := Options.YEnd + (nOldY - Options.YStartOffset); CalcYEnd; Options.PrimaryYAxis.Normalize; @@ -3898,20 +3902,17 @@ end; procedure TJvChart.DrawChartLegendBelow(ACanvas: TCanvas); {accidentally deleted during Jedi_new to Jedi_2009 branch. Restored by WP June 2009} var - I,Y,nTextHeight:Integer; - BoxWidth:Integer; - LLabel:String; + I,Y,nTextHeight:Integer; + BoxWidth:Integer; + LLabel:String; begin + if (Options.Legend <> clChartLegendBelow) then exit; - if (Options.Legend <> clChartLegendBelow) then exit; + if (Options.YStartOffset<=0) or (Options.XStartOffset<=0) then exit; - if (Options.YStartOffset<=0) or (Options.XStartOffset<=0) then exit; - - // space-saving pen-legend below chart - MySmallGraphFont(ACanvas); - - {10 % extra space for line height} - nTextHeight := Round(CanvasMaxTextHeight(ACanvas) * 1.01); + // space-saving pen-legend below chart + MySmallGraphFont(ACanvas); + nTextHeight := CanvasMaxTextHeight(ACanvas); //BoxHeight := nTextHeight - 2; @@ -3922,7 +3923,7 @@ begin if Options.GetPenMarkerKind(I) = pmkNone then Continue; // Skip invisible pens. - Y := Options.YStartOffset + Options.YEnd + (nTextHeight div 2); + Y := Options.YStartOffset + Options.YEnd + X_TITLE_LABEL_DISTANCE; //(nTextHeight div 2); // If chart has X legends: if (Options.XLegends.Count > 0) or Options.XAxisDateTimeMode then @@ -3944,7 +3945,7 @@ begin BoxWidth - 2, {width} nTextHeight - 2, {height} Options.FXLegendHoriz, {X=} - Y + 4); {Y=} + Y + 2); {Y=} end; //SetFontColor(ACanvas, jvChartAxisColorIndex); XXX @@ -3997,6 +3998,8 @@ var { draw x axis text at various alignments:} function LeftXAxisText: Boolean; + var + Y: Integer; begin Result := True; // Don't exceed right margin - causes some undesirable clipping. removed. -wpostma. @@ -4022,9 +4025,8 @@ var begin if Options.FXLegendHoriz < XOverlap then Exit; // would overlap, don't draw it. - MyLeftTextOut(ACanvas, Options.FXLegendHoriz, - {bottom:}FXAxisPosition + Options.AxisLineWidth {top: Round(YTempOrigin - Options.PrimaryYAxis.YPixelGap)}, - Options.XLegends[I]); + Y := FXAxisPosition + Options.AxisLineWidth div 2; + MyLeftTextOut(ACanvas, Options.FXLegendHoriz, Y, Options.XLegends[I]); XOverlap := Options.FXLegendHoriz + ACanvas.TextWidth(Options.XLegends[I]); end else @@ -4032,6 +4034,8 @@ var end; function RightXAxisText: Boolean; + var + Y: Integer; begin Result := True; // Label X axis above or below? @@ -4039,17 +4043,18 @@ var begin if I < Options.XLegends.Count then // fix exception. June 23, 2004- WPostma. MyRightTextOut(ACanvas, Options.FXLegendHoriz, Options.YEnd + 3, Options.XLegends[I]) - end - else + end else if I < Options.XLegends.Count then - MyRightTextOut(ACanvas, Options.FXLegendHoriz, - {bottom:}FXAxisPosition + Options.AxisLineWidth {top: Round(YTempOrigin - Options.PrimaryYAxis.YPixelGap)}, - Options.XLegends[I]) - else + begin + Y := FXAxisPosition + Options.AxisLineWidth div 2; + MyRightTextOut(ACanvas, Options.FXLegendHoriz, Y, Options.XLegends[I]); + end else Result := False; end; function CenterXAxisText: Boolean; + var + Y: Integer; begin Result := True; // Label X axis above or below? @@ -4060,16 +4065,17 @@ var end else if I < Options.XLegends.Count then - MyCenterTextOut(ACanvas, Options.FXLegendHoriz, - {bottom:}FXAxisPosition + Options.AxisLineWidth {top: Round(YTempOrigin - Options.PrimaryYAxis.YPixelGap)}, - Options.XLegends[I]) - else + begin + Y := FXAxisPosition + Options.AxisLineWidth div 2; + MyCenterTextOut(ACanvas, Options.FXLegendHoriz, Y, Options.XLegends[I]); + end else Result := False; end; procedure XAxisDateTimeModeLabels1; // Classic mode [REFACTORED 2007] var L: Integer; + Y: Integer; begin // classic JvChart XAxisDateTime mode labels painting code. @@ -4095,10 +4101,8 @@ var // Check if writing this label would collide with previous label, if not, plot it if (Options.FXLegendHoriz - (ACanvas.TextWidth(TimestampStr) div 2)) > XOverlap then begin - MyCenterTextOut(ACanvas, Options.FXLegendHoriz, - {bottom:}FXAxisPosition + Options.AxisLineWidth - {top: Round(YTempOrigin - Options.PrimaryYAxis.YPixelGap)}, - TimestampStr); + Y := FXAxisPosition + Options.AxisLineWidth div 2; + MyCenterTextOut(ACanvas, Options.FXLegendHoriz, Y, TimeStampStr); // draw a ticky-boo (technical term used by scientists the world over) // so that we can see where on the chart the X axis datetime is pointing to. @@ -4119,7 +4123,7 @@ var procedure XAxisDateTimeModeLabels2; // [NEW 2007] var L: Integer; - X: Integer; + X, Y: Integer; DivPixels: Integer; TextWidth: Integer; Modn: Integer; @@ -4158,9 +4162,8 @@ var if X = Options.XStartOffset then Continue; // don't draw dotted line right at X Axis. - MyCenterTextOut(ACanvas, X, - {bottom:}FXAxisPosition + Options.AxisLineWidth, - TimestampStr); + Y := FXAxisPosition + Options.AxisLineWidth div 2; + MyCenterTextOut(ACanvas, X, Y, TimeStampStr); ACanvas.Pen.Color := Options.GetPenColor(jvChartDivisionLineColorIndex); MyDrawDotLine(ACanvas, X, Options.YStartOffset + 1, X, FXAxisPosition - 1); @@ -4169,8 +4172,8 @@ var procedure DefaultXAxisLegendMode; var - count:Integer; - K:Integer; + count: Integer; + K: Integer; begin {default X axis legend mode: use text legends} if Options.FXAxisLegendSkipBy < 1 then @@ -4185,12 +4188,9 @@ var Options.FXLegendHoriz := Round(Options.XStartOffset + Options.XPixelGap * I ); case Options.FXAxisLabelAlignment of - taLeftJustify: - if not leftXAxisText then break; - taRightJustify: - if not rightXAxisText then break; - taCenter: - if not centerXAxisText then break; + taLeftJustify: if not leftXAxisText then break; + taRightJustify: if not rightXAxisText then break; + taCenter: if not centerXAxisText then break; end; end; {for K} end; {default mode} @@ -4457,6 +4457,27 @@ begin Result := Self.Height; end; +function TJvChart.CalcXAxisTextHeight: Integer; +var + lCanvas: TCanvas; +begin + lCanvas := GetChartCanvas(false); + + Result := TITLE_MARGIN; + + if FOptions.XLegends.Count > 0 then + begin + MyAxisFont(lCanvas); + Result := Result + lCanvas.TextHeight('Tg') + end; + + if FOptions.XAxisHeader <> '' then + begin + MyAxisTitleFont(lCanvas, false); + Result := Result + lCanvas.TextHeight('Tg') + X_TITLE_LABEL_DISTANCE; + end; +end; + procedure TJvChart.CalcYEnd; var aHeight: Integer; @@ -4468,7 +4489,8 @@ begin aHeight := FBitmap.Height; end; - Options.YEnd := aHeight - 2 * Options.YStartOffset; {canvas size, excluding margin} +// Options.YEnd := aHeight - 2 * Options.YStartOffset; {canvas size, excluding margin} + Options.YEnd := aHeight - Options.YStartOffset - CalcXAxisTextHeight; end; @@ -4588,9 +4610,11 @@ begin if StrText = '' then exit; - H := ACanvas.TextHeight(StrText); MyAxisFont(ACanvas); - Y := Options.YStartOffset + Options.YEnd + Round(1.6 * H); + H := ACanvas.TextHeight(StrText); // Height of labels + + MyAxisTitleFont(ACanvas, false); + Y := Options.YStartOffset + Options.YEnd + H + X_TITLE_LABEL_DISTANCE; if Options.Legend = clChartLegendBelow then begin { left aligned X Axis Title, right after the legend itself} @@ -4611,17 +4635,19 @@ var begin if Length(StrText) = 0 then Exit; + ACanvas.Brush.Color := Color; - ACanvas.Font.Assign(FOptions.AxisTitleFont); + MyAxisTitleFont(ACanvas, true); + if Options.XStartOffset > 10 then begin WD := ACanvas.TextWidth(StrText); //Vert := Options.YStartOffset + WD; // top-aligned Vert := Max(0, Options.YStartOffset + (Options.YEnd + WD) div 2); // centered Horiz := 2; - MyLeftTextOut(ACanvas, Horiz, Vert, StrText); + MyLeftTextOut(ACanvas, Horiz, Vert, StrText, true); end; - MyAxisFont(ACanvas); +// MyAxisFont(ACanvas); end; @@ -5427,7 +5453,7 @@ begin MyHeaderFont(ACanvas); MyCenterTextOut(ACanvas, (Options.XStartOffset + Round(Options.XEnd)) div 2, - (Options.YStartOffset - MyTextHeight(ACanvas, StrText)) div 2, + TITLE_MARGIN, StrText ); MyAxisFont(ACanvas); @@ -5449,6 +5475,19 @@ begin ACanvas.Font.Assign(Options.AxisFont); end; +procedure TJvChart.MyAxisTitleFont(ACanvas: TCanvas; Vertical: Boolean); +const + ORIENTATION: Array[boolean] of Integer = (0, 900); +begin + Assert(Assigned(ACanvas)); + Assert(Assigned(ACanvas.Brush)); + Assert(Assigned(ACanvas.Font)); + Assert(Assigned(Options)); + ACanvas.Brush.Color := Options.PaperColor; // was hard coded to clWhite. + ACanvas.Font.Assign(Options.AxisTitleFont); + ACanvas.Font.Orientation := ORIENTATION[Vertical]; +end; + (* { !!warning: uses Win32 only font-handle stuff!!} @@ -5498,11 +5537,20 @@ end; { Text Left Aligned to X,Y boundary } -procedure TJvChart.MyLeftTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string); +procedure TJvChart.MyLeftTextOut(ACanvas: TCanvas; X, Y: Integer; + const AText: string; Vertical: Boolean = false); begin Assert(Assigned(ACanvas)); Assert(Assigned(ACanvas.Brush)); ACanvas.Brush.Color := Options.PaperColor; // non default paper color. + {$IFDEF TEXT_BOX} + ACanvas.Brush.Style := bsSolid; + if Vertical then + ACanvas.Rectangle(X, Y, X + ACanvas.TextHeight(AText), Y - ACanvas.TextWidth(AText)) + else + ACanvas.Rectangle(X, Y, X + ACanvas.TextWidth(AText), Y + ACanvas.TextHeight(AText)); + ACanvas.Brush.Style := bsClear; + {$ENDIF} ACanvas.TextOut(X, Y + 1, AText); end; @@ -5511,6 +5559,11 @@ begin Assert(Assigned(ACanvas)); Assert(Assigned(ACanvas.Brush)); ACanvas.Brush.Color := Options.HintColor; + {$IFDEF TEXT_BOX} + ACanvas.Brush.Style := bsSolid; + ACanvas.Rectangle(X, Y, X + ACanvas.TextWidth(AText), Y + ACanvas.TextHeight(AText)); + ACanvas.Brush.Style := bsClear; + {$ENDIF} ACanvas.TextOut(X, Y + 1, AText); end; @@ -5519,7 +5572,14 @@ begin Assert(Assigned(ACanvas)); Assert(Assigned(ACanvas.Brush)); ACanvas.Brush.Color := Options.PaperColor; // non default paper color. - ACanvas.TextOut(X - Round(ACanvas.TextWidth(AText) / 2), Y + 1, AText); + X := X - ACanvas.TextWidth(AText) div 2; + Y := Y + 1; + {$IFDEF TEXT_BOX} + ACanvas.Brush.Style := bsSolid; + ACanvas.Rectangle(X, Y, X + ACanvas.TextWidth(AText), Y + ACanvas.TextHeight(AText)); + ACanvas.Brush.Style := bsClear; + {$ENDIF} + ACanvas.TextOut(X, Y, AText); end; procedure TJvChart.MyRightTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string); @@ -5527,11 +5587,14 @@ begin Assert(Assigned(ACanvas)); Assert(Assigned(ACanvas.Brush)); ACanvas.Brush.Color := Options.PaperColor; // non default paper color. - ACanvas.TextOut( - X - ACanvas.TextWidth(AText), - Y - Round(ACanvas.TextHeight(AText) / 2), - AText - ); + X := X - ACanvas.TextWidth(AText); + Y := Y - ACanvas.TextHeight(AText) div 2; + {$IFDEF TEXT_BOX} + ACanvas.Brush.Style := bsSolid; + ACanvas.Rectangle(X, Y, X + ACanvas.TextWidth(AText), Y + ACanvas.TextHeight(AText)); + ACanvas.Brush.Style := bsClear; + {$ENDIF} + ACanvas.TextOut(X, Y, AText); end; procedure TJvChart.MyRectangle(ACanvas: TCanvas; X, Y, X2, Y2: Integer);