home *** CD-ROM | disk | FTP | other *** search
- {********************************************************}
- { }
- { TGraphBldr }
- { IMPORTANT-READ CAREFULLY: }
- { }
- { This End-User License Agreement is a legal }
- { agreement between you (either an individual }
- { or a single entity) and Pisarev Yuriy for }
- { the software product identified above, which }
- { includes computer software and may include }
- { associated media, printed materials, and "online" }
- { or electronic documentation ("SOFTWARE PRODUCT"). }
- { By installing, copying, or otherwise using the }
- { SOFTWARE PRODUCT, you agree to be bound by the }
- { terms of this LICENSE AGREEMENT. }
- { }
- { If you do not agree to the terms of this }
- { LICENSE AGREEMENT, do not install or use }
- { the SOFTWARE PRODUCT. }
- { }
- { License conditions }
- { }
- { No part of the software or the manual may be }
- { multiplied, disseminated or processed in any }
- { way without the written consent of Pisarev }
- { Yuriy. Violations of these conditions will be }
- { prosecuted in every case. }
- { }
- { The use of the software is done at your own }
- { risk. The manufacturer and developer accepts }
- { no liability for any damages, either as direct }
- { or indirect consequence of the use of this }
- { product or software. }
- { }
- { Only observance of these conditions allows you }
- { to use the hardware and software in your computer }
- { system. }
- { }
- { All rights reserved. }
- { Copyright 2002 Pisarev Yuriy }
- { }
- { yuriy_mbox@hotmail.com }
- { }
- {********************************************************}
-
- unit GraphBldr;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Classes, Controls, ExtCtrls, Graphics, Math,
- DataEditor;
-
- type
- TPoints = array of array of TPoint;
- TCoord = record
- X, Y: Double;
- end;
- TTraceEvent = procedure(Sender: TObject; X, Y: Double) of object;
- TGraphBldr = class(TCustomControl)
- private
- FTracing: Boolean;
- FShowAxis: Boolean;
- FShowText: Boolean;
- FShowGrid: Boolean;
- FVertSpacing: Double;
- FHorzSpacing: Double;
- FCurrXValue: Double;
- FMargin: Integer;
- FXValueID: Integer;
- FBorderSize: Integer;
- FYMaxValue: Integer;
- FXMaxValue: Integer;
- FDetailLevel: Integer;
- FPicture: TBitmap;
- FSavedBrush: TBrush;
- FDataEditor: TDataEditor;
- FAxisFont: TFont;
- FTextFont: TFont;
- FGridPen: TPen;
- FSaved: TPen;
- FTracePen: TPen;
- FGraphPen: TPen;
- FAxisPen: TPen;
- FPoints: TPoints;
- FTracePoints: TPoints;
- FOnTrace: TTraceEvent;
- procedure DeletePoints(var Points: TPoints);
- function NumFunction(FunctionID: Integer; TypeID: Integer;
- var Value1: Double; Value2, Value3: Double): Boolean;
- procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;
- procedure WMSize(var Message: TWMSize); message WM_SIZE;
- function GetBevelWidth: TBevelWidth;
- function GetBorderWidth: TBorderWidth;
- function GetText: string;
- procedure SetAxisFont(const Value: TFont);
- procedure SetBevelWidth(const Value: TBevelWidth);
- procedure SetBorderWidth(const Value: TBorderWidth);
- procedure SetFont(const Value: TFont);
- procedure SetMargin(const Value: Integer);
- procedure SetText(const Value: string);
- protected
- procedure FilterPoints(var Points: TPoints; X, Y: Integer);
- procedure Paint; override;
- property CurrXValue: Double read FCurrXValue write FCurrXValue;
- property Points: TPoints read FPoints write FPoints;
- property SavedBrush: TBrush read FSavedBrush write FSavedBrush;
- property Saved: TPen read FSaved write FSaved;
- property TracePoints: TPoints read FTracePoints write FTracePoints;
- property XValueID: Integer read FXValueID write FXValueID;
- public
- constructor Create (AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Draw; virtual;
- procedure Calculate; virtual;
- procedure Clear; virtual;
- function XCoord(X: Double): Double;
- function YCoord(Y: Double): Double;
- function Coordinates(X, Y: Double): TCoord;
- property BorderSize: Integer read FBorderSize;
- property Picture: TBitmap read FPicture write FPicture;
- property DataEditor: TDataEditor read FDataEditor write FDataEditor;
- property DockManager;
- published
- property Align;
- property Anchors;
- property AutoSize;
- property AxisFont: TFont read FAxisFont write SetAxisFont;
- property AxisPen: TPen read FAxisPen write FAxisPen;
- property BevelInner default bvLowered;
- property BevelOuter default bvRaised;
- property BevelWidth: TBevelWidth read GetBevelWidth write SetBevelWidth;
- property BiDiMode;
- property BorderWidth: TBorderWidth read GetBorderWidth
- write SetBorderWidth default 5;
- property Color;
- property Constraints;
- property Ctl3D;
- property Cursor default crCross;
- property UseDockManager;
- property DetailLevel: Integer read FDetailLevel write FDetailLevel default 1;
- property DockSite;
- property DragCursor;
- property DragKind;
- property DragMode;
- property Enabled;
- property Font;
- property GraphPen: TPen read FGraphPen write FGraphPen;
- property GridPen: TPen read FGridPen write FGridPen;
- property Height default 150;
- property HorzSpacing: Double read FHorzSpacing write FHorzSpacing;
- property Margin: Integer read FMargin write SetMargin default 5;
- property ParentBiDiMode;
- property ParentColor;
- property ParentCtl3D;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property ShowAxis: Boolean read FShowAxis write FShowAxis default True;
- property ShowGrid: Boolean read FShowGrid write FShowGrid default True;
- property ShowHint;
- property ShowText: Boolean read FShowText write FShowText default False;
- property TabOrder;
- property TabStop;
- property Text: string read GetText write SetText;
- property TextFont: TFont read FTextFont write SetFont;
- property TracePen: TPen read FTracePen write FTracePen;
- property Tracing: Boolean read FTracing write FTracing default True;
- property VertSpacing: Double read FVertSpacing write FVertSpacing;
- property Visible;
- property Width default 300;
- property XMaxValue: Integer read FXMaxValue write FXMaxValue default 5;
- property YMaxValue: Integer read FYMaxValue write FYMaxValue default 5;
- property OnCanResize;
- property OnClick;
- property OnConstrainedResize;
- property OnContextPopup;
- property OnDockDrop;
- property OnDockOver;
- property OnDblClick;
- property OnDragDrop;
- property OnDragOver;
- property OnEndDock;
- property OnEndDrag;
- property OnEnter;
- property OnExit;
- property OnGetSiteInfo;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnResize;
- property OnStartDock;
- property OnStartDrag;
- property OnUnDock;
- property OnTrace: TTraceEvent read FOnTrace write FOnTrace;
- end;
-
- procedure Register;
-
- implementation
-
- procedure Register;
- begin
- RegisterComponents('Samples', [TGraphBldr]);
- end;
-
- { TGraphBldr }
-
- procedure TGraphBldr.Calculate;
-
- procedure Split(var Points: TPoints; var Index: Integer);
- begin
- if Length(FPoints[Index]) > 0 then begin
- Index := Length(FPoints);
- SetLength(FPoints, Index + 1);
- end;
- end;
-
- var
- I, J: Integer;
- Index, Value1, Value2, Factor1, Factor2, Factor3: Double;
- Center: TCoord;
- Rect: TRect;
- begin
- FDataEditor.StringToNumScript(AnsiLowerCase(GetText));
- I := ClientWidth;
- J := ClientHeight;
- Center.X := I / 2;
- Center.Y := J / 2;
- Dec(I, FBorderSize);
- Dec(J, FBorderSize);
- Factor1 := (Center.X - FBorderSize) / FXMaxValue;
- Factor2 := (Center.Y - FBorderSize) / FYMaxValue;
- Factor3 := FXMaxValue / I / FDetailLevel;
- Rect := Classes.Rect(FBorderSize, FBorderSize, I, J);
- DeletePoints(FPoints);
- DeletePoints(FTracePoints);
- J := 0;
- SetLength(FPoints, J + 1);
- Index := - FXMaxValue;
- while Index <= FXMaxValue do begin
- FCurrXValue := Index;
- try
- Value2 := Center.Y - FDataEditor.ExecuteNum * Factor2;
- Value1 := Center.X + Index * Factor1;
- if (Value1 >= Rect.Left) and (Value1 <= Rect.Right) and
- (Value2 >= Rect.Top) and (Value2 <= Rect.Bottom) then begin
- I := Length(FPoints[J]);
- SetLength(FPoints[J], I + 1);
- FPoints[J][I].X := Round(Value1);
- FPoints[J][I].Y := Round(Value2);
- end else Split(FPoints, J);
- except
- Split(FPoints, J);
- end;
- Index := Index + Factor3;
- end;
- FilterPoints(FPoints, 1, 1);
- end;
-
- procedure TGraphBldr.Clear;
- begin
- SetText('');
- FDataEditor.Script := nil;
- DeletePoints(FPoints);
- DeletePoints(FTracePoints);
- end;
-
- function TGraphBldr.Coordinates(X, Y: Double): TCoord;
- begin
- Result.X := XCoord(X);
- Result.Y := YCoord(Y);
- end;
-
- constructor TGraphBldr.Create(AOwner: TComponent);
- begin
- inherited;
- BevelInner := bvLowered;
- BevelOuter := bvRaised;
- ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
- csSetCaption, csOpaque, csDoubleClicks, csReplicatable];
- Cursor := crCross;
- Height := 150;
- Width := 300;
- TabStop := False;
- FAxisFont := TFont.Create;
- FAxisPen := TPen.Create;
- FShowAxis := True;
- inherited BorderWidth := 5;
- FMargin := 5;
- FBorderSize := GetBevelWidth + GetBorderWidth + FMargin;
- FDataEditor := TDataEditor.Create(Self);
- with FDataEditor do begin
- RegisterNumFunction(FXValueID, 'x', False, False);
- SortNumFunctionsData;
- OnNumFunction := NumFunction;
- with AttrsManager do begin
- Strings.Add('x');
- UpdateStrings;
- end;
- end;
- FDetailLevel := 1;
- FGraphPen := TPen.Create;
- FGraphPen.Color := clRed;
- FGridPen := TPen.Create;
- with FGridPen do begin
- Color := clGray;
- Style := psDot;
- end;
- FSaved := TPen.Create;
- FSaved.Assign(Canvas.Pen);
- FTextFont := TFont.Create;
- FTracePen := TPen.Create;
- with FTracePen do begin
- Mode := pmNotXor;
- Color := clBlue;
- Style := psDot;
- end;
- FTracing := True;
- FShowGrid := True;
- FHorzSpacing := 1;
- FPicture := TBitmap.Create;
- FPicture.PixelFormat := pf24bit;
- FShowGrid := True;
- FShowText := False;
- FVertSpacing := 1;
- FXMaxValue := 5;
- FYMaxValue := 5;
- end;
-
- procedure TGraphBldr.DeletePoints(var Points: TPoints);
- var
- I: Integer;
- begin
- for I := Low(Points) to High(Points) do Points[I] := nil;
- Points := nil;
- end;
-
- destructor TGraphBldr.Destroy;
- begin
- DeletePoints(FPoints);
- DeletePoints(FTracePoints);
- FAxisFont.Free;
- FAxisPen.Free;
- FGraphPen.Free;
- FGridPen.Free;
- FSaved.Free;
- FTextFont.Free;
- FTracePen.Free;
- FPicture.Free;
- inherited;
- end;
-
- procedure TGraphBldr.Draw;
- begin
- Paint;
- end;
-
- procedure TGraphBldr.FilterPoints(var Points: TPoints; X, Y: Integer);
- var
- I, J, K: Integer;
- Point, NewPoint: TPoint;
- NewPoints: TPoints;
- begin
- SetLength(NewPoints, Length(Points));
- for I := Low(Points) to High(Points) do
- for J := Low(Points[I]) to High(Points[I]) do
- if J = Low(Points[I]) then Point := Points[I][J]
- else begin
- NewPoint.X := Abs(Points[I][J].X - Point.X);
- NewPoint.Y := Abs(Points[I][J].Y - Point.Y);
- if (NewPoint.X >= X) or (NewPoint.Y >= Y) then begin
- K := Length(NewPoints[I]);
- SetLength(NewPoints[I], K + 1);
- NewPoints[I][K] := Points[I][J];
- Point := Points[I][J];
- end;
- end;
- Points := nil;
- Points := NewPoints;
- end;
-
- function TGraphBldr.GetBevelWidth: TBevelWidth;
- begin
- Result := inherited BevelWidth;
- end;
-
- function TGraphBldr.GetBorderWidth: TBorderWidth;
- begin
- Result := inherited BorderWidth;
- end;
-
- function TGraphBldr.GetText: string;
- begin
- Result := FDataEditor.Text;
- end;
-
- function TGraphBldr.NumFunction(FunctionID, TypeID: Integer;
- var Value1: Double; Value2, Value3: Double): Boolean;
- begin
- if FunctionID = FXValueID then Value1 := FCurrXValue
- else begin
- Result := True;
- Exit;
- end;
- Result := False;
- end;
-
- procedure TGraphBldr.Paint;
- const
- Alignments: array[TAlignment] of Longint = (DT_LEFT, DT_RIGHT, DT_CENTER);
- var
- I, J, K: Integer;
- Factor1, Factor2: Double;
- Center: TPoint;
- Points: array of TPoint;
- Value: string;
- Rect: TRect;
- TopColor, BottomColor: TColor;
-
- procedure AdjustColors(Bevel: TBevelCut);
- begin
- TopColor := clBtnHighlight;
- if Bevel = bvLowered then TopColor := clBtnShadow;
- BottomColor := clBtnShadow;
- if Bevel = bvLowered then BottomColor := clBtnHighlight;
- end;
-
- begin
- inherited;
- DeletePoints(FTracePoints);
- with FPicture, Canvas do begin
- I := ClientWidth;
- J := ClientHeight;
- Width := I;
- Height := J;
- Center.X := I div 2;
- Center.Y := J div 2;
- Dec(I, FBorderSize);
- Dec(J, FBorderSize);
- Brush.Color := Color;
- FillRect(ClientRect);
- if FShowGrid and ((FHorzSpacing > 0) or (FVertSpacing > 0)) then begin
- Pen.Assign(FGridPen);
- if FHorzSpacing > 0 then begin
- // ─δΦφα ∩εδεΓΦφ√ ε±Φ X:
- Factor1 := I - Center.X;
- // ─δΦφα Φφ≥σ≡Γαδα:
- Factor2 := Factor1 * FHorzSpacing / FXMaxValue;
- if Factor2 <= Factor1 then begin
- SetRoundMode(rmDown);
- Factor1 := Center.X;
- while Round(Factor1) <= I do begin
- MoveTo(Round(Factor1), FBorderSize);
- LineTo(Round(Factor1), J);
- Factor1 := Factor1 + Factor2;
- end;
- SetRoundMode(rmUp);
- Factor1 := Center.X;
- while Round(Factor1) >= FBorderSize do begin
- MoveTo(Round(Factor1), FBorderSize);
- LineTo(Round(Factor1), J);
- Factor1 := Factor1 - Factor2;
- end;
- end;
- end;
- if FVertSpacing > 0 then begin
- // ─δΦφα ∩εδεΓΦφ√ ε±Φ Y:
- Factor1 := J - Center.Y;
- // ─δΦφα Φφ≥σ≡Γαδα:
- Factor2 := Factor1 * FVertSpacing / FYMaxValue;
- if Factor2 <= Factor1 then begin
- SetRoundMode(rmDown);
- Factor1 := Center.Y;
- while Round(Factor1) <= J do begin
- MoveTo(FBorderSize, Round(Factor1));
- LineTo(I, Round(Factor1));
- Factor1 := Factor1 + Factor2;
- end;
- SetRoundMode(rmUp);
- Factor1 := Center.Y;
- while Round(Factor1) >= FBorderSize do begin
- MoveTo(FBorderSize, Round(Factor1));
- LineTo(I, Round(Factor1));
- Factor1 := Factor1 - Factor2;
- end;
- end;
- end;
- SetRoundMode(rmNearest);
- end;
- if FShowAxis then begin
- Pen.Assign(FAxisPen);
- K := FAxisPen.Width - 1;
- // ╬±ⁿ X:
- MoveTo(FBorderSize + K, Center.Y);
- LineTo(I - K, Center.Y);
- // ╬±ⁿ Y:
- MoveTo(Center.X, J - K);
- LineTo(Center.X, FBorderSize + K);
- Pen.Width := 1;
- Brush.Color := Pen.Color;
- SetLength(Points, 3);
- try
- // ┬σ≡°Φφα ε±Φ X:
- Points[0].X := I - 15;
- Points[0].Y := Center.Y - 10;
- Points[1].X := I;
- Points[1].Y := Center.Y;
- Points[2].X := I - 15;
- Points[2].Y := Center.Y + 10;
- Polygon(Points);
- // ┬σ≡°Φφα ε±Φ Y:
- SetLength(Points, 3);
- Points[0].X := Center.X - 10;
- Points[0].Y := FBorderSize + 15;
- Points[1].X := Center.X;
- Points[1].Y := FBorderSize;
- Points[2].X := Center.X + 10;
- Points[2].Y := FBorderSize + 15;
- Polygon(Points);
- finally
- Points := nil;
- end;
- Brush.Style := bsClear;
- Font.Assign(FAxisFont);
- TextOut(I - TextWidth('X'), Center.Y - 20 - TextHeight('X'), 'X');
- Value := IntToStr(FXMaxValue);
- TextOut(I - TextWidth(Value), Center.Y + 20, Value);
- TextOut(FBorderSize, Center.Y + 20, '-' + Value);
- TextOut(Center.X - 20 - TextWidth('Y'), FBorderSize, 'Y');
- Value := IntToStr(FYMaxValue);
- TextOut(Center.X + 20, FBorderSize, Value);
- TextOut(Center.X + 20, J - TextHeight('-' + Value), '-' + Value);
- end;
- if FShowText then begin
- Brush.Style := bsClear;
- Font.Assign(FTextFont);
- Value := Trim(GetText);
- if Value <> '' then TextOut(FBorderSize, FBorderSize,
- Format('Y = %s', [Value]));
- end;
- Pen.Assign(FGraphPen);
- //for I := Low(FPoints) to High(FPoints) do Polyline(FPoints[I]);
- for I := Low(FPoints) to High(FPoints) do
- for J := Low(FPoints[I]) to High(FPoints[I]) do
- with FPoints[I][J] do if J = Low(FPoints[I]) then MoveTo(X, Y)
- else LineTo(X, Y);
- end;
- Canvas.Pen.Assign(FSaved);
- Canvas.Draw(0, 0, FPicture);
- Rect := ClientRect;
- if BevelOuter <> bvNone then
- begin
- AdjustColors(BevelOuter);
- Frame3D(Canvas, Rect, TopColor, BottomColor, GetBevelWidth);
- end;
- Frame3D(Canvas, Rect, Color, Color, GetBorderWidth);
- if BevelInner <> bvNone then
- begin
- AdjustColors(BevelInner);
- Frame3D(Canvas, Rect, TopColor, BottomColor, GetBevelWidth);
- end;
- end;
-
- procedure TGraphBldr.SetAxisFont(const Value: TFont);
- begin
- FAxisFont.Assign(Value);
- end;
-
- procedure TGraphBldr.SetBevelWidth(const Value: TBevelWidth);
- begin
- inherited BevelWidth := Value;
- FBorderSize := Value + GetBorderWidth + FMargin;
- end;
-
- procedure TGraphBldr.SetBorderWidth(const Value: TBorderWidth);
- begin
- inherited BorderWidth := Value;
- FBorderSize := Value + GetBevelWidth + FMargin;
- end;
-
- procedure TGraphBldr.SetFont(const Value: TFont);
- begin
- FTextFont.Assign(Value);
- end;
-
- procedure TGraphBldr.SetMargin(const Value: Integer);
- begin
- FMargin := Value;
- FBorderSize := Value + GetBevelWidth + GetBorderWidth;
- end;
-
- procedure TGraphBldr.SetText(const Value: string);
- begin
- FDataEditor.Text := Value;
- end;
-
- procedure TGraphBldr.WMMouseMove(var Message: TWMMouseMove);
-
- procedure DrawLines;
- var
- I: Integer;
- begin
- with Canvas do begin
- Pen.Assign(FTracePen);
- for I := Low(FTracePoints) to High(FTracePoints) do
- Polyline(FTracePoints[I]);
- end;
- end;
-
- var
- I, J: Integer;
- Center: TCoord;
- Value1, Value2, Factor: Double;
- Rect: TRect;
- begin
- inherited;
- if not FTracing or (Trim(GetText) = '') then Exit;
- DrawLines;
- I := ClientWidth;
- J := ClientHeight;
- Center.X := I / 2;
- Center.Y := J / 2;
- Dec(I, FBorderSize);
- Dec(J, FBorderSize);
- Factor := (Center.Y - FBorderSize) / FYMaxValue;
- Rect := Classes.Rect(FBorderSize, FBorderSize, I, J);
- FCurrXValue := XCoord(Message.XPos);
- try
- Value1 := FDataEditor.ExecuteNum;
- Value2 := Center.Y - Value1 * Factor;
- if (Message.XPos >= Rect.Left) and (Message.XPos <= Rect.Right) and
- (Value2 >= Rect.Top) and (Value2 <= Rect.Bottom) then begin
- if Assigned(FOnTrace) then FOnTrace(Self, FCurrXValue, Value1);
- SetLength(FTracePoints, 2);
- SetLength(FTracePoints[0], 2);
- SetLength(FTracePoints[1], 2);
- FTracePoints[0][0].X := Round(Message.XPos);
- FTracePoints[0][0].Y := FBorderSize;
- FTracePoints[0][1].X := Round(Message.XPos);
- FTracePoints[0][1].Y := J;
- FTracePoints[1][0].X := FBorderSize;
- FTracePoints[1][0].Y := Round(Value2);
- FTracePoints[1][1].X := I;
- FTracePoints[1][1].Y := Round(Value2);
- end else DeletePoints(FTracePoints);
- except
- DeletePoints(FTracePoints);
- end;
- DrawLines;
- end;
-
- procedure TGraphBldr.WMSize(var Message: TWMSize);
- begin
- inherited;
- if Trim(GetText) <> '' then Calculate else DeletePoints(FPoints);
- Paint;
- end;
-
- function TGraphBldr.XCoord(X: Double): Double;
- var
- Center: Double;
- begin
- Center := ClientWidth / 2 - FBorderSize;
- Result := (X - FBorderSize - Center) * FXMaxValue / Center;
- end;
-
- function TGraphBldr.YCoord(Y: Double): Double;
- var
- Center: Double;
- begin
- Center := ClientHeight / 2 - FBorderSize;
- Result := (Center - (Y - FBorderSize)) * FYMaxValue / Center;
- end;
-
- end.
-