LazStats: Integrate report and chart into form of BoxPlotUnit. Some minor refactoring.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7682 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-09-21 21:39:40 +00:00
parent 24083f5582
commit 57b8701628
13 changed files with 699 additions and 569 deletions

View File

@ -1,177 +1,174 @@
object BoxPlotFrm: TBoxPlotFrm
Left = 440
Height = 365
Top = 119
Width = 361
Left = 1155
Height = 387
Top = 194
Width = 817
HelpType = htKeyword
HelpKeyword = 'html/BoxPlots.htm'
AutoSize = True
Caption = 'Box Plot'
ClientHeight = 365
ClientWidth = 361
ClientHeight = 387
ClientWidth = 817
OnActivate = FormActivate
OnCreate = FormCreate
Position = poMainFormCenter
LCLVersion = '2.1.0.0'
object ParamsPanel: TPanel
Left = 8
Height = 371
Top = 8
Width = 333
Align = alLeft
BorderSpacing.Around = 8
BevelOuter = bvNone
ClientHeight = 371
ClientWidth = 333
TabOrder = 0
object CloseBtn: TButton
AnchorSideRight.Control = Owner
AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Owner
AnchorSideBottom.Control = ParamsPanel
AnchorSideBottom.Side = asrBottom
Left = 294
Left = 278
Height = 25
Top = 332
Top = 346
Width = 55
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Bottom = 8
Caption = 'Close'
ModalResult = 11
OnClick = CloseBtnClick
TabOrder = 7
TabOrder = 10
end
object ComputeBtn: TButton
AnchorSideRight.Control = CloseBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Control = ParamsPanel
AnchorSideBottom.Side = asrBottom
Left = 210
Left = 194
Height = 25
Top = 332
Top = 346
Width = 76
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Compute'
OnClick = ComputeBtnClick
TabOrder = 6
TabOrder = 9
end
object ResetBtn: TButton
AnchorSideRight.Control = ComputeBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Control = ParamsPanel
AnchorSideBottom.Side = asrBottom
Left = 148
Left = 132
Height = 25
Top = 332
Top = 346
Width = 54
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Reset'
OnClick = ResetBtnClick
TabOrder = 5
TabOrder = 8
end
object HelpBtn: TButton
Tag = 108
AnchorSideRight.Control = ResetBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Control = ParamsPanel
AnchorSideBottom.Side = asrBottom
Left = 89
Left = 73
Height = 25
Top = 332
Top = 346
Width = 51
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 12
BorderSpacing.Top = 8
BorderSpacing.Bottom = 8
BorderSpacing.Right = 8
Caption = 'Help'
OnClick = HelpBtnClick
TabOrder = 4
TabOrder = 7
end
object Bevel2: TBevel
AnchorSideLeft.Control = Owner
AnchorSideRight.Control = Owner
AnchorSideLeft.Control = ParamsPanel
AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = CloseBtn
Left = 0
Height = 8
Top = 316
Width = 361
Top = 330
Width = 333
Anchors = [akLeft, akRight, akBottom]
Shape = bsBottomLine
end
object Label1: TLabel
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = Owner
Left = 8
AnchorSideLeft.Control = ParamsPanel
AnchorSideTop.Control = ParamsPanel
Left = 0
Height = 15
Top = 8
Top = 0
Width = 97
BorderSpacing.Left = 8
BorderSpacing.Top = 8
Caption = 'Available Variables'
ParentColor = False
end
object VarList: TListBox
AnchorSideLeft.Control = Owner
AnchorSideLeft.Control = ParamsPanel
AnchorSideTop.Control = Label1
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = HorCenterBevel
AnchorSideRight.Control = MeasInBtn
AnchorSideBottom.Control = Bevel2
Left = 8
Height = 291
Top = 25
Width = 168
Left = 0
Height = 313
Top = 17
Width = 145
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Left = 8
BorderSpacing.Top = 2
BorderSpacing.Right = 8
Constraints.MinHeight = 200
ItemHeight = 0
OnClick = VarListClick
OnDblClick = VarListDblClick
OnSelectionChange = VarListSelectionChange
TabOrder = 0
end
object HorCenterBevel: TBevel
AnchorSideLeft.Control = Owner
AnchorSideLeft.Side = asrCenter
Left = 176
Height = 78
Top = 55
Width = 8
Shape = bsSpacer
end
object Label2: TLabel
AnchorSideLeft.Control = HorCenterBevel
AnchorSideLeft.Control = GrpInBtn
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = Owner
Left = 184
AnchorSideBottom.Control = GroupEdit
Left = 187
Height = 15
Top = 8
Top = 101
Width = 77
BorderSpacing.Top = 8
Anchors = [akLeft, akBottom]
Caption = 'Group Variable'
ParentColor = False
end
object GroupEdit: TEdit
AnchorSideLeft.Control = HorCenterBevel
AnchorSideLeft.Control = GrpInBtn
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = Label2
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Control = CloseBtn
AnchorSideRight.Side = asrBottom
Left = 184
AnchorSideBottom.Control = GrpOutBtn
AnchorSideBottom.Side = asrBottom
Left = 187
Height = 23
Top = 25
Width = 169
Anchors = [akTop, akLeft, akRight]
Top = 118
Width = 146
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Top = 2
BorderSpacing.Right = 8
TabOrder = 1
BorderSpacing.Bottom = 12
TabOrder = 6
Text = 'GroupEdit'
end
object Label3: TLabel
AnchorSideLeft.Control = MeasEdit
AnchorSideBottom.Control = MeasEdit
Left = 184
Left = 187
Height = 15
Top = 142
Top = 21
Width = 112
Anchors = [akLeft, akBottom]
BorderSpacing.Bottom = 2
@ -179,46 +176,117 @@ object BoxPlotFrm: TBoxPlotFrm
ParentColor = False
end
object MeasEdit: TEdit
AnchorSideLeft.Control = HorCenterBevel
AnchorSideLeft.Control = MeasOutBtn
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = VarList
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = Owner
AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom
Left = 184
AnchorSideBottom.Control = MeasOutBtn
AnchorSideBottom.Side = asrBottom
Left = 187
Height = 23
Top = 159
Width = 169
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Right = 8
TabOrder = 2
Top = 38
Width = 146
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8
BorderSpacing.Bottom = 12
TabOrder = 3
Text = 'MeasEdit'
end
object GroupBox1: TGroupBox
AnchorSideLeft.Control = HorCenterBevel
AnchorSideLeft.Side = asrBottom
object GrpInBtn: TBitBtn
AnchorSideLeft.Control = ParamsPanel
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = MeasOutBtn
AnchorSideTop.Side = asrBottom
Left = 153
Height = 26
Top = 97
Width = 26
BorderSpacing.Left = 8
BorderSpacing.Top = 24
BorderSpacing.Right = 8
Images = MainDataModule.ImageList
ImageIndex = 1
OnClick = GrpInBtnClick
Spacing = 0
TabOrder = 4
end
object GrpOutBtn: TBitBtn
AnchorSideLeft.Control = ParamsPanel
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = GrpInBtn
AnchorSideTop.Side = asrBottom
Left = 153
Height = 26
Top = 127
Width = 26
BorderSpacing.Top = 4
Images = MainDataModule.ImageList
ImageIndex = 0
OnClick = GrpOutBtnClick
Spacing = 0
TabOrder = 5
end
object MeasInBtn: TBitBtn
AnchorSideLeft.Control = ParamsPanel
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = VarList
AnchorSideBottom.Control = MeasOutBtn
Left = 153
Height = 26
Top = 17
Width = 26
BorderSpacing.Left = 8
BorderSpacing.Right = 8
BorderSpacing.Bottom = 4
Images = MainDataModule.ImageList
ImageIndex = 1
OnClick = MeasInBtnClick
Spacing = 0
TabOrder = 1
end
object MeasOutBtn: TBitBtn
AnchorSideLeft.Control = ParamsPanel
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = MeasInBtn
AnchorSideTop.Side = asrBottom
AnchorSideBottom.Control = VarList
AnchorSideBottom.Side = asrBottom
Left = 184
Height = 51
Top = 265
Width = 143
Anchors = [akLeft, akBottom]
AutoSize = True
Caption = 'Options'
ChildSizing.LeftRightSpacing = 12
ChildSizing.TopBottomSpacing = 6
ChildSizing.VerticalSpacing = 2
ClientHeight = 31
ClientWidth = 139
TabOrder = 3
object ShowChk: TCheckBox
Left = 12
Height = 19
Top = 6
Width = 115
Caption = 'Show Frequencies'
TabOrder = 0
Left = 153
Height = 26
Top = 47
Width = 26
BorderSpacing.Top = 4
Images = MainDataModule.ImageList
ImageIndex = 0
OnClick = MeasOutBtnClick
Spacing = 0
TabOrder = 2
end
end
object ParamsSplitter: TSplitter
Left = 349
Height = 387
Top = 0
Width = 5
ResizeStyle = rsPattern
end
object PageControl1: TPageControl
Left = 362
Height = 371
Top = 8
Width = 447
ActivePage = ReportPage
Align = alClient
BorderSpacing.Around = 8
TabIndex = 0
TabOrder = 2
object ReportPage: TTabSheet
Caption = 'Report'
end
object ChartPage: TTabSheet
Caption = 'Chart'
end
end
end

View File

@ -3,14 +3,13 @@
unit BoxPlotUnit;
{$mode objfpc}{$H+}
{$I ../../../LazStats.inc}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, Printers,
MainUnit, Globals, DataProcs, OutputUnit, ContextHelpUnit;
StdCtrls, ExtCtrls, Printers, ComCtrls, Buttons,
MainUnit, Globals, DataProcs, ContextHelpUnit, ReportFrameUnit, ChartFrameUnit;
type
@ -18,38 +17,48 @@ type
{ TBoxPlotFrm }
TBoxPlotFrm = class(TForm)
HorCenterBevel: TBevel;
Bevel2: TBevel;
HelpBtn: TButton;
PageControl1: TPageControl;
ParamsPanel: TPanel;
ResetBtn: TButton;
ComputeBtn: TButton;
CloseBtn: TButton;
ShowChk: TCheckBox;
GroupBox1: TGroupBox;
MeasEdit: TEdit;
GroupEdit: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
ParamsSplitter: TSplitter;
ReportPage: TTabSheet;
ChartPage: TTabSheet;
VarList: TListBox;
GrpInBtn: TBitBtn;
GrpOutBtn: TBitBtn;
MeasInBtn: TBitBtn;
MeasOutBtn: TBitBtn;
procedure CloseBtnClick(Sender: TObject);
procedure ComputeBtnClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure GrpOutBtnClick(Sender: TObject);
procedure GrpInBtnClick(Sender: TObject);
procedure HelpBtnClick(Sender: TObject);
procedure MeasInBtnClick(Sender: TObject);
procedure MeasOutBtnClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure VarListClick(Sender: TObject);
procedure VarListDblClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; User: boolean);
private
{ private declarations }
FAutoSized: Boolean;
FReportFrame: TReportFrame;
FChartFrame: TChartFrame;
procedure BoxPlot(const LowQrtl, HiQrtl, TenPcnt, NinetyPcnt, Medians: DblDyneVec);
function Percentile(nScoreGrps: integer; APercentile: Double;
const Freq, CumFreq, Scores: DblDyneVec): double;
{$IFDEF USE_TACHART}
procedure BoxPlot(const LowQrtl, HiQrtl, TenPcnt, NinetyPcnt, Medians: DblDyneVec);
{$ELSE}
procedure BoxPlot(NBars: integer; AMax, AMin: double;
const LowQrtl, HiQrtl, TenPcnt, NinetyPcnt, Means, Median: DblDyneVec);
{$ENDIF}
procedure UpdateBtnStates;
public
{ public declarations }
@ -64,12 +73,7 @@ implementation
{$R *.lfm}
uses
{$IFDEF USE_TACHART}
TAChartUtils, TAMultiSeries,
ChartUnit,
{$ELSE}
BlankFrmUnit,
{$ENDIF}
TAChartUtils, TALegend, TAMultiSeries,
Math, Utils;
const
@ -78,43 +82,46 @@ const
{ TBoxPlotFrm }
procedure TBoxPlotFrm.Reset;
procedure TBoxPlotFrm.BoxPlot(const LowQrtl, HiQrtl, TenPcnt, NinetyPcnt, Medians: DblDyneVec);
var
i: integer;
i: Integer;
ser: TBoxAndWhiskerSeries;
clr: TColor;
nBars: Integer;
begin
VarList.Clear;
GroupEdit.Text := '';
MeasEdit.Text := '';
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
nBars := Length(LowQrtl);
if (nBars <> Length(HiQrtl)) or (nBars <> Length(TenPcnt)) or
(nBars <> Length(NinetyPcnt)) or (nBars <> Length(Medians)) then
begin
ErrorMsg('Box-Plot: all data arrays must have the same lengths.');
exit;
end;
FChartFrame.Clear;
// Titles
FChartFrame.SetTitle('Box-and-Whisker Plot for ' + OS3MainFrm.FileNameEdit.Text);
FChartFrame.SetFooter('BLACK: median, BOX: 25th to 75th percentile, WHISKERS: 10th and 90th percentile');
FChartFrame.SetXTitle(GroupEdit.Text);
FChartFrame.SetYTitle(MeasEdit.Text);
ser := TBoxAndWhiskerSeries.create(FChartFrame);
for i := 0 to nBars-1 do
begin
clr := BOX_COLORS[i mod Length(BOX_COLORS)];
ser.AddXY(i+1, TenPcnt[i], LowQrtl[i], Medians[i], HiQrtl[i], NinetyPcnt[i], '', clr);
end;
FChartFrame.Chart.BottomAxis.Marks.Source := ser.ListSource;
FChartFrame.Chart.BottomAxis.Marks.Style := smsXValue;
FChartFrame.Chart.AddSeries(ser);
FChartFrame.UpdateBtnStates;
end;
procedure TBoxPlotFrm.ResetBtnClick(Sender: TObject);
procedure TBoxPlotFrm.CloseBtnClick(Sender: TObject);
begin
Reset;
end;
procedure TBoxPlotFrm.VarListClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
if (GroupEdit.Text = '') then
GroupEdit.Text := VarList.Items[index]
else
MeasEdit.Text := VarList.Items[index];
end;
end;
procedure TBoxPlotFrm.HelpBtnClick(Sender: TObject);
begin
if ContextHelpForm = nil then
Application.CreateForm(TContextHelpForm, ContextHelpForm);
ContextHelpForm.HelpMessage((Sender as TButton).tag);
Close;
end;
@ -122,13 +129,11 @@ procedure TBoxPlotFrm.ComputeBtnClick(Sender: TObject);
var
lReport: TStrings;
i, j, k, GrpVar, MeasVar, mingrp, maxgrp, G, NoGrps, cnt: integer;
nScoreGrps: integer;
X, tmp: Double;
// X, tenpcnt, ninepcnt, qrtile1, qrtile2, qrtile3: double;
nScoreGrps, numValues: integer;
X: Double;
MinScore, MaxScore, IntervalSize, lastX: double;
cellstring: string;
done: boolean;
NoSelected: integer;
Freq: DblDyneVec = nil;
Scores: DblDyneVec = nil;
CumFreq: DblDyneVec = nil;
@ -140,7 +145,7 @@ var
TenPcntile: DblDyneVec = nil;
NinetyPcntile: DblDyneVec = nil;
Median: DblDyneVec = nil;
ColNoSelected: IntDyneVec = nil;
ColNoSelected: IntDyneVec;
begin
lReport := TStringList.Create;
try
@ -166,8 +171,7 @@ begin
exit;
end;
NoSelected := 2;
SetLength(ColNoSelected, NoSelected);
SetLength(ColNoSelected, 2);
ColNoSelected[0] := GrpVar;
ColNoSelected[1] := MeasVar;
@ -176,7 +180,7 @@ begin
maxGrp := -MaxInt;
for i := 1 to NoCases do
begin
if not GoodRecord(i, NoSelected, ColNoSelected) then continue;
if not GoodRecord(i, Length(ColNoSelected), ColNoSelected) then continue;
G := round(StrToFloat(OS3MainFrm.DataGrid.Cells[GrpVar, i]));
minGrp := Min(G, minGrp);
maxGrp := Max(G, maxGrp);
@ -194,9 +198,11 @@ begin
X := StrToFloat(OS3MainFrm.DataGrid.Cells[MeasVar, 1]);
MinScore := X;
MaxScore := X;
numValues := 0;
for i := 1 to NoCases do
begin
if not GoodRecord(i, NoSelected ,ColNoSelected) then continue;
if not GoodRecord(i, Length(ColNoSelected), ColNoSelected) then continue;
inc(numValues);
X := StrToFloat(OS3MainFrm.DataGrid.Cells[MeasVar, i]);
MaxScore := Max(MaxScore, X);
MinScore := Min(MinScore, X);
@ -209,12 +215,12 @@ begin
lastX := X;
end;
SetLength(Scores, 2*NoCases + 1); // over-dimensioned, will be trimmed later.
SetLength(Scores, 2*numValues + 1); // over-dimensioned, will be trimmed later.
// check for excess no. of intervals and reset if needed
nScoreGrps := round((MaxScore - MinScore) / IntervalSize);
if nScoreGrps > 2 * NoCases then
Intervalsize := (MaxScore - MinScore) / NoCases;
if nScoreGrps > 2 * numValues then
Intervalsize := (MaxScore - MinScore) / numValues;
// setup score groups
done := false;
@ -260,7 +266,7 @@ begin
cnt := 0;
for i := 1 to NoCases do
begin // get scores for this group j
if not GoodRecord(i,NoSelected, ColNoSelected) then continue;
if not GoodRecord(i, Length(ColNoSelected), ColNoSelected) then continue;
G := round(StrToFloat(OS3MainFrm.DataGrid.Cells[GrpVar, i]));
G := G - minGrp + 1;
if G = j+1 then // subject in this group
@ -274,8 +280,16 @@ begin
Freq[k] := Freq[k] + 1.0;
end;
end;
GrpSize[j] := cnt;
if GrpSize[j] > 0 then Means[j] := Means[j] / GrpSize[j];
if GrpSize[j] = 0 then
begin
Means[j] := NaN;
Median[j] := NaN;
Continue;
end;
Means[j] := Means[j] / GrpSize[j];
// accumulate frequencies
CumFreq[0] := Freq[0];
@ -295,13 +309,11 @@ begin
Median[j] := Percentile(nScoreGrps, 0.50 * GrpSize[j], Freq, CumFreq, Scores);
HiQrtl[j] := Percentile(nScoreGrps, 0.75 * GrpSize[j], Freq, CumFreq, Scores);
if ShowChk.Checked then
begin
if j > 0 then lReport.Add('');
lReport.Add('RESULTS FOR GROUP %d, MEAN = %.3f', [j+1, Means[j]]);
lReport.Add('RESULTS FOR GROUP %d, MEAN %.3f', [j+1, Means[j]]);
lReport.Add('');
lReport.Add('Centile Value');
lReport.Add('------------ ------');
lReport.Add('------------ -------');
lReport.Add('Ten %6.3f', [TenPcntile[j]]);
lReport.Add('Twenty five %6.3f', [LowQrtl[j]]);
lReport.Add('Median %6.3f', [Median[j]]);
@ -315,20 +327,13 @@ begin
Scores[i], Scores[i+1], Freq[i], CumFreq[i], pRank[i]
]);
lReport.Add('');
end;
end; // get values for next group
// Show the report with the frequencies
if ShowChk.Checked then
DisplayReport(lReport);
FReportFrame.DisplayReport(lReport);
// Plot the boxes
{$IFDEF USE_TACHART}
BoxPlot(LowQrtl, HiQrtl, TenPcntile, NinetyPcntile, Median);
{$ELSE}
BoxPlot(NoGrps, MaxScore, MinScore, LowQrtl, HiQrtl, TenPcntile, NinetyPcntile, Means, Median);
{$ENDIF}
finally
lReport.Free;
@ -348,12 +353,6 @@ begin
end;
procedure TBoxPlotFrm.CloseBtnClick(Sender: TObject);
begin
Close;
end;
procedure TBoxPlotFrm.FormActivate(Sender: TObject);
var
w: Integer;
@ -367,8 +366,17 @@ begin
ComputeBtn.Constraints.MinWidth := w;
CloseBtn.Constraints.MinWidth := w;
Constraints.MinWidth := Width;
Constraints.MinHeight := Height;
ParamsPanel.Constraints.MinWidth := Max(
4*w + 3*HelpBtn.BorderSpacing.Right,
Max(Label1.Width, Label3.Width) * 2 + MeasInBtn.Width + 2 * MeasInBtn.BorderSpacing.Left
);
ParamsPanel.Constraints.MinHeight := VarList.Top + VarList.Constraints.MinHeight +
Bevel2.Height + CloseBtn.Height + CloseBtn.BorderSpacing.Top;
Constraints.MinHeight := ParamsPanel.Constraints.MinHeight + ParamsPanel.BorderSpacing.Around*2;
Constraints.MinWidth := ParamsPanel.Constraints.MinWidth + 200;
if Height < Constraints.MinHeight then Height := 1; // Enforce autosizing
if Width < Constraints.MinWidth then Width := 1;
Position := poDesigned;
FAutoSized := true;
@ -378,10 +386,82 @@ end;
procedure TBoxPlotFrm.FormCreate(Sender: TObject);
begin
Assert(OS3MainFrm <> nil);
FReportFrame := TReportFrame.Create(self);
FReportFrame.Parent := ReportPage;
FReportFrame.Align := alClient;
FChartFrame := TChartFrame.Create(self);
FChartFrame.Parent := ChartPage;
FChartFrame.Align := alClient;
FChartFrame.Chart.Legend.Alignment := laBottomCenter;
FChartFrame.Chart.Legend.ColumnCount := 3;
FChartFrame.Chart.Legend.TextFormat := tfHTML;
FChartFrame.Chart.BottomAxis.Intervals.MaxLength := 80;
FChartFrame.Chart.BottomAxis.Intervals.MinLength := 30;
InitToolbar(FChartFrame.ChartToolbar, tpTop);
Reset;
end;
procedure TBoxPlotFrm.GrpInBtnClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if (index > -1) and (GroupEdit.Text = '') then
begin
GroupEdit.Text := VarList.Items[index];
VarList.Items.Delete(index);
UpdateBtnStates;
end;
end;
procedure TBoxPlotFrm.GrpOutBtnClick(Sender: TObject);
begin
if GroupEdit.Text <> '' then
begin
VarList.Items.Add(GroupEdit.Text);
GroupEdit.Text := '';
UpdateBtnStates;
end;
end;
procedure TBoxPlotFrm.HelpBtnClick(Sender: TObject);
begin
if ContextHelpForm = nil then
Application.CreateForm(TContextHelpForm, ContextHelpForm);
ContextHelpForm.HelpMessage((Sender as TButton).tag);
end;
procedure TBoxPlotFrm.MeasInBtnClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if (index > -1) and (MeasEdit.Text = '') then
begin
MeasEdit.Text := VarList.Items[index];
VarList.Items.Delete(index);
UpdateBtnStates;
end;
end;
procedure TBoxPlotFrm.MeasOutBtnClick(Sender: TObject);
begin
if MeasEdit.Text <> '' then
begin
VarList.Items.Add(MeasEdit.Text);
MeasEdit.Text := '';
UpdateBtnStates;
end;
end;
function TBoxPlotFrm.Percentile(nScoreGrps: integer;
APercentile: double; const Freq, CumFreq, Scores: DblDyneVec): double;
var
@ -404,8 +484,7 @@ begin
ULimit := Scores[interval+1];
cumLower := CumFreq[interval-1];
intervalFreq := Freq[interval];
end
else
end else
begin // Percentile in first interval
LLimit := Scores[0];
ULimit := Scores[1];
@ -420,180 +499,59 @@ begin
end;
{$IFDEF USE_TACHART}
procedure TBoxPlotFrm.BoxPlot(const LowQrtl, HiQrtl, TenPcnt, NinetyPcnt, Medians: DblDyneVec);
procedure TBoxPlotFrm.Reset;
var
i: Integer;
ser: TBoxAndWhiskerSeries;
clr: TColor;
nBars: Integer;
i: integer;
begin
nBars := Length(LowQrtl);
if (nBars <> Length(HiQrtl)) or (nBars <> Length(TenPcnt)) or
(nBars <> Length(NinetyPcnt)) or (nBars <> Length(Medians)) then
begin
ErrorMsg('Box-Plot: all data arrays must have the same lengths.');
exit;
VarList.Clear;
GroupEdit.Text := '';
MeasEdit.Text := '';
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
UpdateBtnStates;
end;
if ChartForm = nil then
ChartForm := TChartForm.Create(Application)
procedure TBoxPlotFrm.ResetBtnClick(Sender: TObject);
begin
Reset;
end;
procedure TBoxPlotFrm.UpdateBtnStates;
begin
MeasinBtn.Enabled := (VarList.ItemIndex > -1) and (MeasEdit.Text = '');
MeasoutBtn.Enabled := (MeasEdit.Text <> '');
GrpinBtn.Enabled := (VarList.ItemIndex > -1) and (GroupEdit.Text = '');
grpoutBtn.Enabled := (GroupEdit.Text <> '');
FReportFrame.UpdateBtnStates;
FChartFrame.UpdateBtnStates;
end;
procedure TBoxPlotFrm.VarListDblClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
if MeasEdit.Text = '' then
MeasEdit.Text := VarList.Items[index]
else
ChartForm.Clear;
GroupEdit.Text := VarList.Items[index];
end;
VarList.Items.Delete(index);
UpdateBtnStates;
end;
// Titles
ChartForm.SetTitle('Box-and-Whisker Plot for ' + OS3MainFrm.FileNameEdit.Text);
ChartForm.SetFooter('BLACK: median, BOX: 25th to 75th percentile, WHISKERS: 10th and 90th percentile');
ChartForm.SetXTitle(GroupEdit.Text);
ChartForm.SetYTitle(MeasEdit.Text);
ser := TBoxAndWhiskerSeries.create(ChartForm);
for i := 0 to nBars-1 do
procedure TBoxPlotFrm.VarListSelectionChange(Sender: TObject; User: boolean);
begin
clr := BOX_COLORS[i mod Length(BOX_COLORS)];
ser.AddXY(i+1, TenPcnt[i], LowQrtl[i], Medians[i], HiQrtl[i], NinetyPcnt[i], '', clr);
UpdateBtnStates;
end;
ChartForm.ChartFrame.Chart.BottomAxis.Marks.Source := ser.ListSource;
ChartForm.ChartFrame.Chart.BottomAxis.Marks.Style := smsXValue;
ChartForm.ChartFrame.Chart.AddSeries(ser);
ChartForm.Show;
end;
{$ELSE}
procedure TBoxPlotFrm.BoxPlot(NBars: integer; AMax, AMin: double;
const LowQrtl, HiQrtl, TenPcnt, NinetyPcnt, Means, Median: DblDyneVec);
var
i, HTickSpace, imagewide, imagehi, vtop, vbottom, offset: integer;
vhi, hleft, hright, hwide, barwidth, Xpos, Ypos, strhi: integer;
XOffset, YOffset: integer;
X, Y: integer;
X1, X2, X3, X9, X10: integer; // X coordinates for box and lines
Y1, Y2, Y3, Y4, Y9: integer; // Y coordinates for box and lines
Title: string;
valincr, Yvalue: double;
begin
if BlankFrm = nil then Application.CreateForm(TBlankFrm, BlankFrm);
BlankFrm.Show;
imagewide := BlankFrm.Image1.width;
imagehi := BlankFrm.Image1.Height;
XOffset := imagewide div 10;
YOffset := imagehi div 10;
vtop := YOffset;
vbottom := imagehi - YOffset;
vhi := vbottom - vtop;
hleft := XOffset;
hright := imagewide - hleft - XOffset;
hwide := hright - hleft;
HTickSpace := hwide div nbars;
barwidth := HTickSpace div 2;
// Show title
Title := 'BOXPLOT FOR : ' + OS3MainFrm.FileNameEdit.Text;
BlankFrm.Caption := Title;
(*
// show legend
Y := BlankFrm.Image1.Canvas.TextHeight(Title) * 2;
Y := Y + vtop;
Title := 'RED: mean, BLACK: median, BOX: 25th to 75th percentile, WISKERS: 10th and 90th percentile';
X := imagewide div 2 - BlankFrm.Canvas.TextWidth(Title) div 2;
BlankFrm.Image1.Canvas.TextOut(X,Y,Title);
*)
// Draw chart background and border
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
BlankFrm.Image1.Canvas.Rectangle(0,0,imagewide,imagehi);
// show legend
Y := 2;
Title := 'RED: mean, BLACK: median, BOX: 25th to 75th percentile, WISKERS: 10th and 90th percentile';
X := imagewide div 2 - BlankFrm.Canvas.TextWidth(Title) div 2;
BlankFrm.Image1.Canvas.TextOut(X,Y,Title);
// Draw vertical axis
valincr := (AMax - AMin) / 20.0;
for i := 1 to 21 do
begin
Title := format('%8.2f',[AMax - ((i-1)*valincr)]);
strhi := BlankFrm.Image1.Canvas.TextHeight(Title);
xpos := XOffset;
Yvalue := AMax - (valincr * (i-1));
ypos := round(vhi * ( (AMax - Yvalue) / (AMax - AMin)));
ypos := ypos + vtop - strhi div 2;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
end;
BlankFrm.Image1.Canvas.MoveTo(hleft,vtop);
BlankFrm.Image1.Canvas.LineTo(hleft,vbottom);
// draw horizontal axis
BlankFrm.Image1.Canvas.MoveTo(hleft,vbottom + 10 );
BlankFrm.Image1.Canvas.LineTo(hright,vbottom + 10);
for i := 1 to nbars do
begin
ypos := vbottom + 10;
xpos := round((hwide / nbars)* i + hleft);
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
ypos := ypos + 10;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
Title := format('%d',[i]);
offset := BlankFrm.Image1.Canvas.TextWidth(Title) div 2;
strhi := BlankFrm.Image1.Canvas.TextHeight(Title);
xpos := xpos - offset;
ypos := ypos + strhi - 2;
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
xpos := 20;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,'GROUPS:');
end;
for i := 0 to NBars - 1 do
begin
BlankFrm.Image1.Canvas.Brush.Color := BOX_COLORS[i mod Length(BOX_COLORS)];
// plot the box front face
X9 := round(hleft + ((i+1) * HTickSpace) - (barwidth / 2));
X10 := X9 + barwidth;
X1 := X9;
X2 := X10;
Y1 := round((((AMax - HiQrtl[i]) / (AMax - AMin)) * vhi) + vtop);
Y2 := round((((AMax - LowQrtl[i]) / (AMax - AMin)) * vhi) + vtop);
BlankFrm.Image1.Canvas.Rectangle(X1,Y1,X2,Y2);
// draw upper 90th percentile line and end
X3 := round(X1 + barwidth / 2);
BlankFrm.Image1.Canvas.MoveTo(X3,Y1);
Y3 := round((((AMax - NinetyPcnt[i]) / (AMax - AMin)) * vhi) + vtop);
BlankFrm.Image1.Canvas.LineTo(X3,Y3);
BlankFrm.Image1.Canvas.MoveTo(X1,Y3);
BlankFrm.Image1.Canvas.LineTo(X2,Y3);
// draw lower 10th percentile line and end
BlankFrm.Image1.Canvas.MoveTo(X3,Y2);
Y4 := round((((AMax - TenPcnt[i]) / (AMax - AMin)) * vhi) + vtop);
BlankFrm.Image1.Canvas.LineTo(X3,Y4);
BlankFrm.Image1.Canvas.MoveTo(X1,Y4);
BlankFrm.Image1.Canvas.LineTo(X2,Y4);
//plot the means line
BlankFrm.Image1.Canvas.Pen.Color := clRed;
BlankFrm.Image1.Canvas.Pen.Style := psDot;
Y9 := round((((AMax - Means[i]) / (AMax - AMin)) * vhi) + vtop);
BlankFrm.Image1.Canvas.MoveTo(X9,Y9);
BlankFrm.Image1.Canvas.LineTo(X10,Y9);
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
BlankFrm.Image1.Canvas.Pen.Style := psSolid;
//plot the median line
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
Y9 := round((((AMax - Median[i]) / (AMax - AMin)) * vhi) + vtop);
BlankFrm.Image1.Canvas.MoveTo(X9,Y9);
BlankFrm.Image1.Canvas.LineTo(X10,Y9);
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
end;
end;
{$ENDIF}
end.

View File

@ -59,6 +59,7 @@ object DescriptiveFrm: TDescriptiveFrm
BorderSpacing.Bottom = 8
ItemHeight = 0
MultiSelect = True
OnDblClick = VarListDblClick
OnSelectionChange = VarListSelectionChange
TabOrder = 0
end
@ -89,6 +90,7 @@ object DescriptiveFrm: TDescriptiveFrm
BorderSpacing.Left = 8
BorderSpacing.Top = 2
ItemHeight = 0
OnDblClick = SelListDblClick
OnSelectionChange = VarListSelectionChange
TabOrder = 4
end

View File

@ -46,6 +46,8 @@ type
procedure InBtnClick(Sender: TObject);
procedure OutBtnClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure SelListDblClick(Sender: TObject);
procedure VarListDblClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; User: boolean);
private
@ -469,11 +471,41 @@ begin
FReportFrame.Clear;
end;
procedure TDescriptiveFrm.ResetBtnClick(Sender: TObject);
begin
Reset;
end;
procedure TDescriptiveFrm.SelListDblClick(Sender: TObject);
var
index: integer;
begin
index := SelList.ItemIndex;
if index > -1 then
begin
VarList.Items.Add(SelList.Items[index]);
SelList.Items.Delete(index);
UpdateBtnStates;
end;
end;
procedure TDescriptiveFrm.VarListDblClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
SelList.Items.Add(VarList.Items[index]);
VarList.Items.Delete(index);
UpdateBtnStates;
end;
end;
procedure TDescriptiveFrm.UpdateBtnStates;
var
lSelected: Boolean;

View File

@ -104,11 +104,12 @@ object PlotXYFrm: TPlotXYFrm
Left = 0
Height = 274
Top = 17
Width = 166
Width = 167
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Top = 2
BorderSpacing.Bottom = 8
ItemHeight = 0
OnDblClick = VarListDblClick
OnSelectionChange = VarListSelectionChange
TabOrder = 3
end
@ -116,9 +117,9 @@ object PlotXYFrm: TPlotXYFrm
AnchorSideLeft.Control = XEdit
AnchorSideTop.Side = asrBottom
AnchorSideBottom.Control = XEdit
Left = 210
Left = 209
Height = 15
Top = 23
Top = 19
Width = 76
Anchors = [akLeft, akBottom]
BorderSpacing.Bottom = 2
@ -128,9 +129,9 @@ object PlotXYFrm: TPlotXYFrm
object Label3: TLabel
AnchorSideLeft.Control = YEdit
AnchorSideBottom.Control = YEdit
Left = 210
Left = 209
Height = 15
Top = 109
Top = 101
Width = 76
Anchors = [akLeft, akBottom]
BorderSpacing.Bottom = 2
@ -141,10 +142,10 @@ object PlotXYFrm: TPlotXYFrm
AnchorSideLeft.Control = ParamsPanel
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = VarList
Left = 174
Height = 28
Left = 175
Height = 26
Top = 17
Width = 28
Width = 26
BorderSpacing.Left = 8
BorderSpacing.Right = 8
Images = MainDataModule.ImageList
@ -158,10 +159,10 @@ object PlotXYFrm: TPlotXYFrm
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = XinBtn
AnchorSideTop.Side = asrBottom
Left = 174
Height = 28
Top = 49
Width = 28
Left = 175
Height = 26
Top = 47
Width = 26
BorderSpacing.Top = 4
Images = MainDataModule.ImageList
ImageIndex = 0
@ -175,10 +176,10 @@ object PlotXYFrm: TPlotXYFrm
AnchorSideTop.Control = XOutBtn
AnchorSideTop.Side = asrBottom
AnchorSideBottom.Control = YOutBtn
Left = 174
Height = 28
Top = 101
Width = 28
Left = 175
Height = 26
Top = 97
Width = 26
BorderSpacing.Top = 24
BorderSpacing.Bottom = 4
Images = MainDataModule.ImageList
@ -194,10 +195,10 @@ object PlotXYFrm: TPlotXYFrm
AnchorSideTop.Side = asrBottom
AnchorSideBottom.Control = VarList
AnchorSideBottom.Side = asrBottom
Left = 174
Height = 28
Top = 133
Width = 28
Left = 175
Height = 26
Top = 127
Width = 26
BorderSpacing.Top = 4
Images = MainDataModule.ImageList
ImageIndex = 0
@ -212,10 +213,10 @@ object PlotXYFrm: TPlotXYFrm
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = XOutBtn
AnchorSideBottom.Side = asrBottom
Left = 210
Left = 209
Height = 23
Top = 42
Width = 158
Top = 38
Width = 159
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8
BorderSpacing.Top = 4
@ -231,10 +232,10 @@ object PlotXYFrm: TPlotXYFrm
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = YOutBtn
AnchorSideBottom.Side = asrBottom
Left = 210
Left = 209
Height = 23
Top = 126
Width = 166
Top = 118
Width = 167
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Bottom = 12
ReadOnly = True
@ -246,9 +247,9 @@ object PlotXYFrm: TPlotXYFrm
AnchorSideTop.Control = YEdit
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 174
Left = 175
Height = 120
Top = 173
Top = 165
Width = 191
AutoSize = True
BorderSpacing.Top = 24

View File

@ -46,6 +46,7 @@ type
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure VarListDblClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
procedure XinBtnClick(Sender: TObject);
procedure XOutBtnClick(Sender: TObject);
@ -105,6 +106,23 @@ begin
end;
procedure TPlotXYFrm.VarListDblClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
if XEdit.Text = '' then
XEdit.Text := VarList.Items[index]
else
YEdit.Text := VarList.Items[index];
VarList.Items.Delete(index);
UpdateBtnStates;
end;
end;
procedure TPlotXYFrm.XinBtnClick(Sender: TObject);
var
index: integer;
@ -385,8 +403,7 @@ begin
Marks.Style := smsLabel;
Grid.Visible := false;
end;
FChartFrame.ChartToolbar.Transparent := false;
FChartFrame.ChartToolbar.Color := clForm;
InitToolbar(FChartFrame.ChartToolbar, tpTop);
Reset;
end;
@ -462,8 +479,12 @@ procedure TPlotXYFrm.UpdateBtnStates;
begin
XinBtn.Enabled := (VarList.ItemIndex > -1) and (XEdit.Text = '');
XoutBtn.Enabled := (XEdit.Text <> '');
YinBtn.Enabled := (VarList.ItemIndex > -1) and (YEdit.Text = '');
YoutBtn.Enabled := (YEdit.Text <> '');
FReportFrame.UpdateBtnStates;
FChartFrame.UpdateBtnStates;
end;

View File

@ -129,21 +129,22 @@ object BasicSPCForm: TBasicSPCForm
Left = 0
Height = 363
Top = 25
Width = 158
Width = 157
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Top = 2
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
ItemHeight = 0
OnClick = VarListClick
OnDblClick = VarListDblClick
TabOrder = 0
end
object GroupLabel: TLabel
AnchorSideLeft.Control = GroupEdit
AnchorSideTop.Control = GroupInBtn
Left = 198
Left = 199
Height = 15
Top = 93
Top = 99
Width = 105
BorderSpacing.Top = 2
BorderSpacing.Bottom = 2
@ -157,10 +158,10 @@ object BasicSPCForm: TBasicSPCForm
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = SpecsPanel
AnchorSideRight.Side = asrBottom
Left = 198
Left = 199
Height = 23
Top = 110
Width = 159
Top = 116
Width = 158
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 8
BorderSpacing.Top = 2
@ -172,7 +173,7 @@ object BasicSPCForm: TBasicSPCForm
object MeasLabel: TLabel
AnchorSideLeft.Control = MeasEdit
AnchorSideTop.Control = MeasInBtn
Left = 198
Left = 199
Height = 15
Top = 27
Width = 117
@ -188,10 +189,10 @@ object BasicSPCForm: TBasicSPCForm
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = SpecsPanel
AnchorSideRight.Side = asrBottom
Left = 198
Left = 199
Height = 23
Top = 44
Width = 159
Width = 158
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 8
BorderSpacing.Top = 2
@ -213,10 +214,10 @@ object BasicSPCForm: TBasicSPCForm
AnchorSideLeft.Control = SpecsPanel
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = VarList
Left = 166
Height = 24
Left = 165
Height = 26
Top = 25
Width = 24
Width = 26
Images = MainDataModule.ImageList
ImageIndex = 1
OnClick = MeasInBtnClick
@ -226,10 +227,10 @@ object BasicSPCForm: TBasicSPCForm
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = MeasInBtn
AnchorSideTop.Side = asrBottom
Left = 167
Height = 22
Top = 53
Width = 23
Left = 165
Height = 26
Top = 55
Width = 26
BorderSpacing.Top = 4
Images = MainDataModule.ImageList
ImageIndex = 0
@ -240,10 +241,10 @@ object BasicSPCForm: TBasicSPCForm
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = MeasOutBtn
AnchorSideTop.Side = asrBottom
Left = 166
Height = 24
Top = 91
Width = 24
Left = 165
Height = 26
Top = 97
Width = 26
BorderSpacing.Top = 16
Images = MainDataModule.ImageList
ImageIndex = 1
@ -254,10 +255,10 @@ object BasicSPCForm: TBasicSPCForm
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = GroupInBtn
AnchorSideTop.Side = asrBottom
Left = 167
Height = 22
Top = 119
Width = 23
Left = 165
Height = 26
Top = 127
Width = 26
BorderSpacing.Top = 4
Images = MainDataModule.ImageList
ImageIndex = 0

View File

@ -47,6 +47,7 @@ type
procedure MeasOutBtnClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure VarListClick(Sender: TObject);
procedure VarListDblClick(Sender: TObject);
private
FGroupsNeeded: Boolean;
@ -187,6 +188,7 @@ begin
Marks.Source := TListChartSource.Create(self);
Marks.Style := smsLabel;
end;
InitToolbar(FChartFrame.ChartToolbar, tpTop);
Reset;
end;
@ -420,5 +422,21 @@ begin
UpdateBtnStates;
end;
procedure TBasicSPCForm.VarListDblClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
if MeasEdit.Text = '' then
MeasEdit.Text := VarList.Items[index]
else
GroupEdit.Text := VarList.Items[index];
end;
VarList.Items.Delete(index);
UpdateBtnStates;
end;
end.

View File

@ -1987,11 +1987,8 @@ end;
procedure TOS3MainFrm.mnuAnalysisDescr_BubblePlotClick(Sender: TObject);
begin
if BubbleForm = nil then
begin
Application.CreateForm(TBubbleForm, BubbleForm);
BubbleForm.Position := poMainFormCenter;
end;
BubbleForm.ShowModal;
BubbleForm.Show;
end;
// Menu "Analysis" > "Descriptive" > "Compare mnuAnalysisDescr_DistribStats"
@ -2022,10 +2019,7 @@ end;
procedure TOS3MainFrm.mnuAnalysisDescr_DistribStatsClick(Sender: TObject);
begin
if DescriptiveFrm = nil then
begin
Application.CreateForm(TDescriptiveFrm, DescriptiveFrm);
DescriptiveFrm.Position := poMainFormCenter;
end;
DescriptiveFrm.Show;
end;
@ -2095,11 +2089,8 @@ end;
procedure TOS3MainFrm.mnuAnalysisDescr_PlotXvsYClick(Sender: TObject);
begin
if PlotXYFrm = nil then
begin
Application.CreateForm(TPlotXYFrm, PlotXYFrm);
PlotXYFrm.Position := poMainFormCenter;
end;
PlotXYFrm.ShowModal;
PlotXYFrm.Show;
end;
procedure TOS3MainFrm.mnuAnalysisDescr_ResistanceLineClick(Sender: TObject);

View File

@ -9,10 +9,10 @@ object ChartFrame: TChartFrame
DesignLeft = 518
DesignTop = 150
object Chart: TChart
Left = 6
Height = 367
Top = 30
Width = 608
Left = 0
Height = 379
Top = 24
Width = 620
AxisList = <
item
Grid.Color = clSilver
@ -36,6 +36,8 @@ object ChartFrame: TChartFrame
Foot.Brush.Color = clBtnFace
Foot.Brush.Style = bsClear
Foot.Font.Color = clBlue
MarginsExternal.Top = 8
MarginsExternal.Right = 8
Title.Brush.Color = clBtnFace
Title.Brush.Style = bsClear
Title.Font.Color = clBlue
@ -45,9 +47,6 @@ object ChartFrame: TChartFrame
)
Toolset = ChartToolset
Align = alClient
BorderSpacing.Left = 6
BorderSpacing.Right = 6
BorderSpacing.Bottom = 6
Color = clWhite
end
object ChartToolBar: TToolBar
@ -56,7 +55,6 @@ object ChartFrame: TChartFrame
Top = 0
Width = 620
AutoSize = True
BorderSpacing.Bottom = 6
ButtonHeight = 22
ButtonWidth = 25
Caption = 'ChartToolBar'

View File

@ -49,25 +49,30 @@ object ReportFrame: TReportFrame
end
end
object ReportPanel: TPanel
Left = 6
Height = 204
Left = 4
Height = 206
Top = 30
Width = 298
Width = 302
Align = alClient
BorderSpacing.Around = 6
BorderSpacing.Around = 4
BevelOuter = bvNone
BorderStyle = bsSingle
ClientHeight = 200
ClientWidth = 294
ClientHeight = 202
ClientWidth = 298
Color = clWhite
ParentColor = False
TabOrder = 1
object ReportMemo: TMemo
Left = 4
Height = 192
Height = 194
Top = 4
Width = 286
Width = 294
Align = alClient
BorderSpacing.Around = 4
BorderSpacing.Left = 4
BorderSpacing.Top = 4
BorderSpacing.Bottom = 4
BorderStyle = bsNone
Color = clWhite
Font.Height = -11
Font.Name = 'Courier New'
ParentFont = False

View File

@ -26,7 +26,6 @@ type
procedure tbSaveReportClick(Sender: TObject);
private
FPrintY: Integer;
FMaxLen: Integer;
function LongestLine(AReport: TStrings): Integer;
protected
@ -76,6 +75,8 @@ var
maxLen: Integer;
s: String;
begin
ReportMemo.Lines.BeginUpdate;
try
if not Add then
ReportMemo.Clear;
@ -85,6 +86,9 @@ begin
ReportMemo.Lines.Add(AddChar('-', '', maxLen))
else
ReportMemo.Lines.Add(s);
finally
Reportmemo.Lines.EndUpdate;
end;
UpdateBtnStates;
end;

View File

@ -5,10 +5,14 @@ unit Utils;
interface
uses
Classes, SysUtils, StdCtrls, ComCtrls, Dialogs,
Classes, SysUtils, Graphics, Controls, StdCtrls, ComCtrls, Dialogs,
Globals;
type
TToolbarPosition = (tpTop, tpLeft, tpRight);
procedure AddButtonToToolbar(AToolButton: TToolButton; AToolBar: TToolBar);
procedure InitToolbar(AToolbar: TToolbar; APosition: TToolbarPosition);
function AnySelected(AListbox: TListBox): Boolean;
@ -27,6 +31,9 @@ function IndexOfString(L: StrDyneVec; s: String): Integer;
implementation
uses
ToolWin;
// https://stackoverflow.com/questions/4093595/create-ttoolbutton-runtime
procedure AddButtonToToolbar(AToolButton: TToolButton; AToolBar: TToolBar);
var
@ -41,6 +48,30 @@ begin
end;
procedure InitToolbar(AToolbar: TToolbar; APosition: TToolbarPosition);
begin
// AToolbar.Transparent := false;
// AToolbar.Color := clForm;
case APosition of
tpTop:
begin
AToolbar.Align := alTop;
AToolbar.EdgeBorders := [ebBottom];
end;
tpLeft:
begin
AToolbar.Align := alLeft;
AToolbar.EdgeBorders := [ebRight];
end;
tpRight:
begin
AToolbar.Align := alRight;
AToolbar.EdgeBorders := [ebLeft];
end;
end;
end;
function AnySelected(AListBox: TListBox): Boolean;
var
i: Integer;