Normal

A cross-platform example

Click here to see how it looks (100K gif).

Or get the whole code here.


Normal.dpr

program Normal;

uses
{$IFDEF WIN32}
  Forms,
{$ENDIF}
{$IFDEF LINUX}
{Note the pre-pending of "Q" to Forms for Clx:}
  QForms,
{$ENDIF}
  Normal1 in 'Normal1.pas' {MainForm};

{Ensure that your resource files' extension really is ".res" and not ".RES".}  
{$R *.res}

begin
  Application.Initialize;
  Application.Title := 'Normal for Linux';
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;
end.


Normal.pas

unit Normal1;

{$I Chemware.inc}

interface

uses
  SysUtils, Classes, TypInfo, // units common to Delphi and Kylix
{$IFDEF WIN32} // Windows units
  Windows, Messages, 
  Graphics, Controls, Forms, Dialogs,
  ImgList, Menus, Grids, ExtCtrls, StdCtrls,
  Buttons, ComCtrls, ToolWin, 
{$ENDIF}
{$IFDEF LINUX} // Kylix equivalents that link to Qt
{Note the pre-pending of "Q" for many Clx units:}
  Qt, Types, // you rarely need to pull in Qt directly
  QGraphics, QControls, QForms, QDialogs,
  QImgList, QMenus, QGrids, QExtCtrls, QStdCtrls,
  QButtons, QComCtrls,
{$ENDIF}

{our own cross-platform units. Be very very careful about case sensitivity !}
  Plot, Plotdefs, Plotmenu, Plotimagelist, Data, Plottoolbar, Nedit;

type
  TMainForm = class(TForm)
    Panel1: TPanel;
    StringGrid1: TStringGrid;
    MinNEdit: TNEdit;
    Label1: TLabel;
    Label2: TLabel;
    MaxNEdit: TNEdit;
    Label3: TLabel;
    StepSizeNEdit: TNEdit;
    Label4: TLabel;
    MeanNEdit: TNEdit;
    Label5: TLabel;
    StdDevNEdit: TNEdit;
    GoBitBtn: TBitBtn;
    GoCrazyBitBtn: TBitBtn;
    CrazyTimer: TTimer;
    ClearAllBitBtn: TBitBtn;
    NoisyBitBtn: TBitBtn;
    TraceBitBtn: TBitBtn;
    TypeBitBtn: TBitBtn;
    StatusBar1: TStatusBar;
    procedure ClearAllBitBtnClick(Sender: TObject);
    procedure GoBitBtnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PlotMenu1ExitMenuItemClick(Sender: TObject);
    procedure NoisyBitBtnClick(Sender: TObject);
    procedure GoCrazyBitBtnClick(Sender: TObject);
    procedure CrazyTimerTimer(Sender: TObject);
    procedure MyPlotFileOpen(Sender: TObject; TheFile: String);
    procedure TraceBitBtnClick(Sender: TObject);
    procedure TypeBitBtnClick(Sender: TObject);
  private
    MyPlot: TPlot;
    MyPlotMenu: TPlotMenu;
    MyPlotImageList: TPlotImageList;
    MyPlotToolBar: TPlotToolBar;
    Revolutions,
    StartWidth,
    StartHeight: Integer;
    Angle,
    AngleInc: Single;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{Note the lower case "dfm":}
{$R *.dfm}

const
  RADIUS = 50.0;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Height := 516;
  Width := 712;

  MyPlotImageList := TPlotImageList.Create(Self);

  MyPlot := TPlot.Create(Self);
  MyPlot.Parent := Self;
  MyPlot.Align := alClient;
  MyPlot.Images := MyPlotImageList;
  MyPlot.PlotType := ptXY;
  MyPlot.NoSeries := 2;
  MyPlot.MakeDummyData(20);

  MyPlotMenu := TPlotMenu.Create(Self);
  MyPlotMenu.Images := MyPlotImageList;
  MyPlotMenu.Plot := MyPlot;
  MyPlotMenu.SetUpOnClicks;

  MyPlotToolBar := TPlotToolBar.Create(Self);
  MyPlotToolBar.Parent := Self;
  MyPlotToolBar.Images := MyPlotImageList;
  MyPlotToolBar.Plot := MyPlot;

  StringGrid1.Cells[0, 0] := 'Test:';
  StringGrid1.Cells[0, 1] := 'Score:';
  StringGrid1.ColWidths[0] := 60;

{$IFDEF WIN32}
  Self.Caption := 'TPlot demo for Delphi';
{$ENDIF}
{$IFDEF LINUX}
  Self.Caption := 'TPlot demo for Kylix';
{$ENDIF}
end;

procedure TMainForm.ClearAllBitBtnClick(Sender: TObject);
var
  i: Integer;
begin
  MyPlot.SeriesList.ClearSeries;
  for i := 1 to StringGrid1.ColCount-1 do
  begin
    StringGrid1.Cells[i, 0] := '';
    StringGrid1.Cells[i, 1] := '';
  end;
end;

procedure TMainForm.GoBitBtnClick(Sender: TObject);
var
  X, Y: Single;
  Mean: Single;
  StdDev: Single;
  Min: Single;
  Max: Single;
  StepSize: Single;
{$IFDEF MSWINDOWS}
  FStartTime:          Int64; {TLargeInteger;}
  FFinishTime:         Int64;
  FFrequency:          Int64;
{$ENDIF}
{$IFDEF LINUX}
  FStartTime:          TDateTime;
  FFinishTime:         TDateTime;
{$ENDIF}
  ElapsedTime: Double;
begin
  MyPlot.NoSeries := 1;
  MyPlot.Series[0].DelData;

  Screen.Cursor := crHourGlass;
{$IFDEF MSWINDOWS}
  QueryPerformanceFrequency(FFrequency); {counts per second}
{get the starting time:}
  QueryPerformanceCounter(FStartTime); { LARGE_INTEGER}
{$ENDIF}
{$IFDEF LINUX}
  FStartTime := Time;
{$ENDIF}

  Mean := MeanNEdit.AsReal;
  StdDev := StdDevNEdit.AsReal;
  Min := MinNEdit.AsReal;
  Max := MaxNEdit.AsReal;
  StepSize := StepSizeNEdit.AsReal;

{Set the axes:}
  MyPlot.XAxis.Max := Max;
  MyPlot.XAxis.Min := Min;
  MyPlot.YAxis.Min := 0;
  MyPlot.XAxis.Intercept := 0;

  X := Min;
  while (X <= Max) do
  begin
    Y := Exp(-Sqr((X-Mean)/(2*StdDev))) /
      Sqrt(2*Pi*StdDev);
{Don't fire any events, and don't adjust axes:}
    MyPlot[0].AddPoint(X, Y, FALSE, FALSE);
    X := X + StepSize;
  end;
  MyPlot[0].Visible := TRUE;

  MyPlot.YAxis.Max := MyPlot.Series[0].YMax;

{get the finishing time:}
{$IFDEF MSWINDOWS}
  QueryPerformanceCounter(FFinishTime); { LARGE_INTEGER}
{take difference and convert to ms:}
  ElapsedTime := 1000 * (FFinishTime - FStartTime) / FFrequency;
{$ENDIF}
{$IFDEF LINUX}
  FFinishTime := Time;
  ElapsedTime := 1000 * (FFinishTime - FStartTime);
{$ENDIF}
  StatusBar1.SimpleText := Format('Drawing %d points takes %g ms',
    [MyPlot[0].NoPts, ElapsedTime]);

  Screen.Cursor := crDefault;
end;

procedure TMainForm.PlotMenu1ExitMenuItemClick(Sender: TObject);
begin
  Close;
end;

procedure TMainForm.NoisyBitBtnClick(Sender: TObject);
begin
  MyPlot.MakeDummyData(100);
end;

procedure TMainForm.GoCrazyBitBtnClick(Sender: TObject);
begin
  if (CrazyTimer.Enabled) then
  begin
    CrazyTimer.Enabled := FALSE;
    GoCrazyBitBtn.Caption := 'Go Crazy';
    TraceBitBtn.Enabled := TRUE;
  end
  else
  begin
    Revolutions := 0;
    StartWidth := Width;
    StartHeight := Height;
    Angle := 0;
    AngleInc := 4 * Pi / 180;
    GoCrazyBitBtn.Caption := 'Enough !';
    CrazyTimer.Enabled := TRUE;
    TraceBitBtn.Enabled := FALSE;
  end;
end;

procedure TMainForm.CrazyTimerTimer(Sender: TObject);
begin
  if (MyPlot.PlotType >= pt3DContour) then
  begin
    MyPlot.ZAngle := MyPlot.ZAngle + 1;
  end
  else
  begin
    Width := StartWidth + Round(RADIUS * Sin(Angle));
    Height := StartHeight + Round(RADIUS * Cos(Angle));
    Angle := Angle + AngleInc;
    Inc(Revolutions);
    StatusBar1.SimpleText := IntToStr(Revolutions);
  end;
end;

procedure TMainForm.MyPlotFileOpen(Sender: TObject; TheFile: String);
var
  TheTitle: String;
begin
  TheTitle := ExtractFileName(Application.ExeName);
  TheTitle := Copy(TheTitle, 1, Length(TheTitle)-4);
  TheTitle := TheTitle + ' - ' + ExtractFileName(TheFile);
  Application.Title := TheTitle;
  MainForm.Caption := TheTitle;
end;

procedure TMainForm.TraceBitBtnClick(Sender: TObject);
begin
  MyPlot.Trace;
end;

procedure TMainForm.TypeBitBtnClick(Sender: TObject);
var
 ThePlotType: Integer;
 TheXStringData: TStringList;
begin
  ThePlotType := Ord(MyPlot.PlotType);
  ThePlotType := (ThePlotType+1) mod (Ord(High(TPlotType))+1);
  MyPlot.SeriesList.ClearSeries;
  MyPlot.PlotType := TPlotType(ThePlotType);
  MyPlot.Title.Caption := 'TPlot - ' + #10 +
    Copy(TypInfo.GetEnumName(TypeInfo(TPlotType), ThePlotType), 3, 99);
  case MyPlot.PlotType of
    ptXY:
      begin
        MyPlot.MakeDummyData(100);
        MyPlot.Border.Left := 70;
        MyPlot.Border.BottomGap := 80;
      end;
    ptError:
      begin
        MyPlot.MakeDummyData(20);
        MyPlot.Series[0].Symbol := syCircle;
      end;
    ptMultiple:
      begin
        MyPlot.NoSeries := 4;
        MyPlot.Multiplicity := 4;
        MyPlot.MakeDummyData(20);
        MyPlot.Series[0].Pen.Width := 0;
        MyPlot.Series[1].Pen.Width := 0;
        MyPlot.Series[2].Pen.Width := 0;
        MyPlot.Series[3].Pen.Width := 0;
        MyPlot.Series[0].Name := 'High';
        MyPlot.Series[1].Name := 'Low';
        MyPlot.Series[2].Name := 'Open';
        MyPlot.Series[3].Name := 'Close';
        MyPlot.Series[0].Symbol := syLeftDash;
        MyPlot.Series[1].Symbol := syRightDash;
        MyPlot.MultiJoin := '2,3';
      end;
    ptBubble:
      begin
        MyPlot.MakeDummyData(20);
      end;
    ptColumn, ptStack, ptNormStack: MyPlot.MakeDummyData(10);
    ptPie:
      begin
        MyPlot.MakeDummyData(10);
        TheXStringData := TStringList.Create;
        TheXStringData.Add('Alpha');
        TheXStringData.Add('Bravo');
        TheXStringData.Add('Charlie');
        TheXStringData.Add('Delta');
        TheXStringData.Add('Echo');
        TheXStringData.Add('Foxtrot');
        TheXStringData.Add('Golf');
        TheXStringData.Add('Hotel');
        TheXStringData.Add('India');
        TheXStringData.Add('Juliet');
        TheXStringData.Add('Kilo');
        MyPlot.Series[0].XStringData := TheXStringData;
        MyPlot.Series[1].XStringData := TheXStringData;
        TheXStringData.Free;
      end;
    ptPolar:
      begin
        MyPlot.XAxis.Min := -10;
        MyPlot.XAxis.Max := 10;
        MyPlot.YAxis.Min := -10;
        MyPlot.YAxis.Max := 10;
        MyPlot.MakeDummyData(20);
        MyPlot.XAxis.Intercept := 0;
        MyPlot.YAxis.Intercept := 0;
      end;
    ptContour, pt3DContour, pt3DWire, pt3DColumn:
      begin
        if (MyPlot.PlotType > ptContour) then
        begin
          MyPlot.Border.Left := 120;
          MyPlot.Border.BottomGap := 130;
        end;
        MyPlot.XAxis.Min := 0;
        MyPlot.XAxis.Max := 10;
        MyPlot.YAxis.Min := 0;
        MyPlot.YAxis.Max := 10;
        MyPlot.NoSeries := 10;
        MyPlot.MakeDummyData(20);
      end;
  else ;
  end;
end;

end.


Mat Ballard
22 June 2001