MMEnvelp.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:45k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Fax.: +49 (0)351-8037944 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/mmtools.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 11.08.98 - 01:23:42 $ =}
- {========================================================================}
- unit MMEnvelp;
- {$I COMPILER.INC}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinProcs,
- WinTypes,
- {$ENDIF}
- SysUtils,
- Messages,
- Classes,
- Graphics,
- Controls,
- Forms,
- Dialogs,
- MMObj,
- MMDIBCv,
- MMPanel,
- MMUtils,
- MMString,
- MMMulDiv,
- MMMath,
- MMObjLst,
- MMPCMSup,
- MMObsrv;
- type
- TMMEnvelopeKind = (ekRectangle, ekCircle, ekOwnerDraw);
- TMMEnvelopeDrawPoint = procedure(Sender: TObject; Canvas: TCanvas;
- Rect: TRect; Selected: Boolean) of object;
- TMMEnvelope = class;
- {-- TMMEnvelopePoint --------------------------------------------------}
- TMMEnvelopePoint = class(TObject)
- private
- procedure Store(S: TStream); virtual;
- procedure Load(S: TStream); virtual;
- public
- X_Value : Longint;
- Y_Value : Longint;
- Selected: Boolean;
- constructor Create;
- constructor CreateEx(X,Y: integer; Sel: Boolean);
- procedure SetParams(X,Y: integer; Sel: Boolean);
- procedure Assign(Source: TObject);
- end;
- {-- TMMEnvelopePointList ----------------------------------------------}
- TMMEnvelopePointList = class(TObjectList)
- private
- FEnvelope: TMMEnvelope;
- procedure PutPoint(Index: integer; Point: TMMEnvelopePoint);
- function GetPoint(Index: integer): TMMEnvelopePoint;
- protected
- procedure ReadData(S: TStream); override;
- procedure WriteData(S: TStream); override;
- public
- procedure Assign(Source: TPersistent); override;
- property Items[Index: integer]: TMMEnvelopePoint read GetPoint write PutPoint; default;
- end;
- {-- TMMEnvelope -------------------------------------------------------}
- TMMEnvelope = class(TMMMarkerPanel)
- private
- FDIBCanvas : TMMDIBCanvas;
- FPoints : TMMEnvelopePointList;
- FTempPoint : TMMEnvelopePoint;
- FKind : TMMEnvelopeKind;
- FPointSize : integer;
- FStartIndex : integer;
- FCurIndex : integer;
- FUpSelect : Boolean;
- FShiftBeginX : Longint; { StartPunkt der MausOperation X values }
- FShiftBeginY : Longint; { StartPunkt der MausOperation Y Values }
- FMinShiftX : Longint; { max Shiftbereich nach links immer negativ }
- FMaxShiftX : Longint; { max Shiftbereich nach rechts immer pos. }
- FMinShiftY : Longint; { max Shiftbereich nach oben immer negativ }
- FMaxShiftY : Longint; { max Shiftbereich nach unten immer pos. }
- FButton : TMouseButton;
- FDragOffset : TPoint;
- FDragRect : TRect;
- FDragging : Boolean;
- FMoving : Boolean;
- FDrawMidLine : Boolean;
- FMidLineColor : TColor;
- FLineColor : TColor;
- FPointColor : TColor;
- FSelectedColor : TColor;
- FMoveFirstPoint : Boolean;
- FMoveLastPoint : Boolean;
- FObservable : TMMObservable;
- FOnChange : TNotifyEvent;
- FOnDrawPoint : TMMEnvelopeDrawPoint;
- procedure SetMovePoints(Index: integer; aValue: Boolean);
- procedure SetKind(aValue: TMMEnvelopeKind);
- procedure SetColors(index: integer; aValue: TColor);
- procedure SetDrawMidLine(aValue: Boolean);
- procedure SetPointSize(aValue: integer);
- procedure SetPoints(aValue: TMMEnvelopePointList);
- function GetCount: integer;
- function Get_YValue(X_Value: Longint): Longint;
- function GetSelected(Index: integer): Boolean;
- procedure SetSelected(Index: integer; aValue: Boolean);
- function GetSelectedCount: integer;
- procedure CreateInitPoints;
- procedure GetMaxRange(Index: integer; var minX, maxX, minY, maxY: Longint);
- procedure RemapPoints(oldMinX,oldMaxX,oldMinY,oldMaxY: Longint);
- procedure DoChanged(Sender: TObject);
- procedure DrawEnvelopePoints(Canvas: TMMDIBCanvas);
- procedure DrawEnvelope;
- protected
- procedure VLineDoted(aCanvas: TCanvas; x, y1, y2: integer; Clr: TColorRef); override;
- procedure HLineDoted(aCanvas:TCanvas;x1,x2,y:integer;Clr:TColorRef); override;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
- X, Y: integer); override;
- procedure MouseMove(Shift: TShiftState; X, Y: integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
- X, Y: integer); override;
- procedure Paint; override;
- procedure Changed; override;
- procedure RangeChanged; override;
- procedure DrawPoint(Canvas: TCanvas; Rect: TRect; Selected: Boolean); dynamic;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
- procedure AddObserver(O: TMMObserver);
- procedure RemoveObserver(O: TMMObserver);
- procedure SetRangeAll(MinX, MaxX, MinY, MaxY, YBase: Longint); override;
- { TODO: einige Eigenschaften verstecken }
- procedure Clear;
- procedure Reset;
- function AddPoint(aPoint: TMMEnvelopePoint; Align: Boolean): Boolean;
- procedure DelPoint(Index: integer);
- function LocatePoint(X_Value: Longint): integer;
- function FindPoint(X_Value: Longint): integer;
- function FindPointAtPos(X, Y: integer): integer;
- function QueryPoint(Point: TMMEnvelopePoint): Boolean;
- procedure DeleteSelected;
- procedure SelectAll(State: Boolean);
- procedure SelectRange(idxA, idxB: integer; State: Boolean);
- procedure SelectArea(Area: TRect; State: Boolean);
- procedure QueryPolyMove(var minX, maxX, minY, maxY: Longint);
- procedure PolyShift(DiffX, DiffY: Longint);
- procedure Scale(Factor: Float);
- property Count: integer read GetCount;
- property YValue[X_Value: Longint]: Longint read Get_YValue;
- property Select[Index: integer]: Boolean read GetSelected write SetSelected;
- property CurrentIndex: integer read FCurIndex;
- property SelectedCount: integer read GetSelectedCount;
- published
- { Events }
- property OnClick;
- property OnDblClick;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnDrawPoint: TMMEnvelopeDrawPoint read FOnDrawPoint write FOnDrawPoint;
- property Align;
- property Bevel;
- property Color default clBtnFace;
- property Width default 200;
- property Height default 100;
- property ParentShowHint;
- property ParentColor default False;
- property ShowHint;
- property Visible;
- property Enabled;
- property Kind: TMMEnvelopeKind read FKind write SetKind default ekRectangle;
- property MidLineColor: TColor index 0 read FMidLineColor write SetColors default clBlack;
- property LineColor: TColor index 1 read FLineColor write SetColors default clBlack;
- property PointColor: TColor index 2 read FPointColor write SetColors default clWhite;
- property SelectedColor: TColor index 3 read FSelectedColor write SetColors default clBlack;
- property PointSize: integer read FPointSize write SetPointSize default 6;
- property DrawMidLine: Boolean read FDrawMidLine write SetDrawMidLine default True;
- property MoveFirstPoint: Boolean index 0 read FMoveFirstPoint write SetMovePoints default True;
- property MoveLastPoint: Boolean index 1 read FMoveLastPoint write SetMovePoints default True;
- property Points: TMMEnvelopePointList read FPoints write SetPoints;
- end;
- implementation
- const
- STREAMKENNUNG : Longint = $00564E45; { 'ENV ' }
- {== TMMEnvelopePoint ====================================================}
- constructor TMMEnvelopePoint.Create;
- begin
- inherited Create;
- X_Value := 0;
- Y_Value := 0;
- Selected := False;
- end;
- {-- TMMEnvelopePoint ----------------------------------------------------}
- constructor TMMEnvelopePoint.CreateEx(X,Y: integer; Sel: Boolean);
- begin
- inherited Create;
- X_Value := X;
- Y_Value := Y;
- Selected := Sel;
- end;
- {-- TMMEnvelopePoint ----------------------------------------------------}
- procedure TMMEnvelopePoint.Store(S: TStream);
- begin
- S.WriteBuffer(X_Value,SizeOf(X_Value));
- S.WriteBuffer(Y_Value,SizeOf(Y_Value));
- S.WriteBuffer(Selected,SizeOf(Selected));
- end;
- {-- TMMEnvelopePoint ----------------------------------------------------}
- procedure TMMEnvelopePoint.Load(S: TStream);
- begin
- S.ReadBuffer(X_Value,SizeOf(X_Value));
- S.ReadBuffer(Y_Value,SizeOf(Y_Value));
- S.ReadBuffer(Selected,SizeOf(Selected));
- end;
- {-- TMMEnvelopePoint ----------------------------------------------------}
- procedure TMMEnvelopePoint.Assign(Source: TObject);
- begin
- if Source is TMMEnvelopePoint then
- begin
- SetParams(TMMEnvelopePoint(Source).X_Value,
- TMMEnvelopePoint(Source).Y_Value,
- TMMEnvelopePoint(Source).Selected);
- end;
- end;
- {-- TMMEnvelopePoint ----------------------------------------------------}
- procedure TMMEnvelopePoint.SetParams(X,Y: integer; Sel: Boolean);
- begin
- X_Value := X;
- Y_Value := Y;
- Selected := Sel;
- end;
- {== TMMEnvelopePointList ================================================}
- procedure TMMEnvelopePointList.PutPoint(Index: integer; Point: TMMEnvelopePoint);
- begin
- Put(Index, Point);
- end;
- {-- TMMEnvelopePointList ------------------------------------------------}
- function TMMEnvelopePointList.GetPoint(Index: integer): TMMEnvelopePoint;
- begin
- Result := TMMEnvelopePoint(Get(Index));
- end;
- {-- TMMEnvelopePointList ------------------------------------------------}
- procedure TMMEnvelopePointList.Assign(Source: TPersistent);
- var
- i: integer;
- pt: TMMEnvelopePoint;
- begin
- if (Source is TMMEnvelopePointList) or (Source = nil) then
- begin
- BeginUpdate;
- try
- FreeAll;
- if (Source <> nil) then
- for i := 0 to TMMEnvelopePointList(Source).Count-1 do
- begin
- pt := TMMEnvelopePoint.Create;
- pt.Assign(TMMEnvelopePointList(Source)[i]);
- pt.Selected := False;
- AddObject(pt);
- end;
- finally
- EndUpdate;
- end;
- exit;
- end;
- inherited assign(Source);
- end;
- {-- TMMEnvelopePointList ------------------------------------------------}
- procedure TMMEnvelopePointList.ReadData(S: TStream);
- Var
- Kennung: Longint;
- ObjCount,
- Index: TOLSize;
- Destroy: Boolean;
- MinX,MaxX,MinY,MaxY: Longint;
- begin
- BeginUpdate;
- try
- S.ReadBuffer(Kennung,sizeOf(STREAMKENNUNG));
- if (Kennung <> STREAMKENNUNG) then
- raise EStreamError.Create('Invalid Object stream');
- FreeAll;
- { load stream items }
- S.ReadBuffer(Destroy,SizeOf(Destroy));
- DestroyObjects := Destroy;
- S.ReadBuffer(MinX,SizeOf(MinX));
- S.ReadBuffer(MaxX,SizeOf(MaxX));
- S.ReadBuffer(MinY,SizeOf(MinY));
- S.ReadBuffer(MaxY,SizeOf(MaxY));
- S.ReadBuffer(ObjCount,SizeOf(Objcount)); { Read in Object count }
- { make sure we have not to much points and load only our limit }
- ObjCount := Min(ObjCount,(FEnvelope.RangeMaxX-FEnvelope.RangeMinX)+1);
- if Capacity-Count < ObjCount then Capacity := Count+ObjCount;
- { Read in Object Count }
- for Index := 0 to ObjCount-1 do
- begin
- AddObject(ReadObjectFromStream(S));
- Items[Index].Selected := False;
- end;
- FEnvelope.RemapPoints(MinX,MaxX,MinY,MaxY);
- finally
- EndUpdate;
- end;
- end;
- {-- TMMEnvelopePointList ------------------------------------------------}
- procedure TMMEnvelopePointList.WriteData(S: TStream);
- var
- Index,
- ObjCount: TOlSize;
- Destroy: Boolean;
- Value: Longint;
- begin
- { Write list to Stream }
- S.WriteBuffer(STREAMKENNUNG,SizeOf(STREAMKENNUNG));
- Destroy := DestroyObjects;
- S.WriteBuffer(Destroy,SizeOf(Destroy));
- Value := FEnvelope.RangeMinX;
- S.WriteBuffer(Value, SizeOf(Value));
- Value := FEnvelope.RangeMaxX;
- S.WriteBuffer(Value, SizeOf(Value));
- Value := FEnvelope.RangeMinY;
- S.WriteBuffer(Value, SizeOf(Value));
- Value := FEnvelope.RangeMaxY;
- S.WriteBuffer(Value, SizeOf(Value));
- ObjCount := Count;
- S.WriteBuffer(ObjCount,SizeOf(ObjCount));
- for Index := 0 to Count-1 do
- WriteObjectToStream(Items[Index],S);
- end;
- {== TMMEnvelope =========================================================}
- constructor TMMEnvelope.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FObservable := TMMObservable.Create;
- FDIBCanvas := TMMDIBCanvas.Create(Self);
- FDIBCanvas.SetBounds(0,0,Width,Height);
- FPoints := TMMEnvelopePointList.Create;
- FPoints.OnChange := DoChanged;
- FPoints.FEnvelope := Self;
- FTempPoint := TMMEnvelopePoint.Create;
- FMoveFirstPoint := True;
- FMoveLastPoint := True;
- FKind := ekRectangle;
- FDragging := False;
- FMoving := False;
- FUpSelect := False;
- FStartIndex := 0;
- FCurIndex := -1;
- FDrawMidLine := True;
- FMidLineColor := clBlack;
- FLineColor := clBlack;
- FPointColor := clWhite;
- FSelectedColor := clBlack;
- FPointSize := 6;
- Width := 200;
- Height := 100;
- Color := clBtnFace;
- CreateInitPoints;
- ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
- if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- destructor TMMEnvelope.Destroy;
- begin
- FDIBCanvas.Free;
- FPoints.Free;
- FTempPoint.Free;
- FObservable.Free;
- FObservable:= nil;
- inherited Destroy;
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.AddObserver(O: TMMObserver);
- begin
- FObservable.AddObserver(O);
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.RemoveObserver(O: TMMObserver);
- begin
- if (FObservable <> nil) then
- FObservable.RemoveObserver(O);
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
- var
- W, H: Integer;
- begin
- W := Width;
- H := Height;
- inherited SetBounds(aLeft, aTop, aWidth, aHeight);
- if ((W <> Width) or (H <> Height)) and
- (Width > 0) and (Height > 0) and (FDIBCanvas <> nil) then
- begin
- FDIBCanvas.SetBounds(0,0,Width,Height);
- Invalidate;
- end;
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.SetPoints(aValue: TMMEnvelopePointList);
- begin
- if (aValue <> FPoints) then FPoints.Assign(aValue);
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.DoChanged(Sender: TObject);
- begin
- Changed;
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.Changed;
- begin
- inherited Changed;
- if not (csReading in ComponentState) and
- not (csLoading in ComponentState) then
- begin
- { go trough the list and notify }
- FObservable.NotifyObservers(Self);
- if assigned(FOnChange) then FOnChange(Self);
- end;
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.SetRangeAll(MinX, MaxX, MinY, MaxY, YBase: Longint);
- var
- oldMinX,oldMaxX,oldMinY,oldMaxY: Longint;
- begin
- if (MinX > MaxX) then SwapLong(MinX, MaxX);
- if (MinY > MaxY) then SwapLong(MinY, MaxY);
- if (MinX <> RangeMinX) or (MaxX <> RangeMaxX) or
- (MinY <> RangeMinY) or (MaxY <> RangeMaxY) or
- (YBase <> BaseY) then
- begin
- oldMinX := RangeMinX;
- oldMaxX := RangeMaxX;
- oldMinY := RangeMinY;
- oldMaxY := RangeMaxY;
- inherited SetRangeAll(MinX,MaxX,MinY,MaxY,YBase);
- RemapPoints(oldMinX,oldMaxX,oldMinY,oldMaxY);
- Invalidate;
- end;
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.RemapPoints(oldMinX,oldMaxX,oldMinY,oldMaxY: Longint);
- var
- i: integer;
- begin
- if Count > 0 then
- for i := 0 to Count-1 do
- begin
- with Points[i] do
- begin
- if (i = 0) then
- X_Value := RangeMinX
- else if (i = Count-1) then
- X_Value := RangeMaxX
- else
- X_Value := Limit(MulDiv32(X_Value-oldMinX,RangeMaxX-RangeMinX,oldMaxX-oldMinX)+RangeMinX,RangeMinX,RangeMaxX);
- Y_Value := Limit(MulDiv32(Y_Value-oldMinY,RangeMaxY-RangeMinY,oldMaxY-oldMinY)+RangeMinY,RangeMinY,RangeMaxY);
- end;
- Changed;
- end;
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.Scale(Factor: Float);
- var
- i: integer;
- von, bis: integer;
- FactorMin, FactorMax: Float;
- Lim1, Lim2: Float;
- begin
- FactorMin := -MaxLongint;
- FactorMax := +MaxLongint;
- von := ord(not FMoveFirstPoint);
- bis := Count-(1+ord(not FMoveLastPoint));
- for i := von to bis do
- if Points[i].Y_Value <> 0 then
- begin
- Lim1 := RangeMinY / Points[i].Y_Value;
- Lim2 := RangeMaxY / Points[i].Y_Value;
- FactorMax := LimitR(FactorMax, Lim1, Lim2);
- FactorMin := LimitR(FactorMin, Lim1, Lim2);
- end;
- Factor := LimitR(Factor, FactorMin, FactorMax);
- if (Factor <> 1.0) then
- begin
- for i := von to bis do
- Points[i].Y_Value := Round(Factor * Points[i].Y_Value);
- Changed;
- end;
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- function TMMEnvelope.GetCount: integer;
- begin
- Result := FPoints.Count;
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- procedure TMMEnvelope.CreateInitPoints;
- begin
- FTempPoint.X_Value := RangeMinX;
- FTempPoint.Y_Value := BaseY;
- FTempPoint.Selected := False;
- AddPoint(FTempPoint,False);
- FTempPoint.X_Value := RangeMaxX;
- FTempPoint.Y_Value := BaseY;
- FTempPoint.Selected := False;
- AddPoint(FTempPoint,False);
- {$IFDEF WIN32}
- {$IFDEF TRIAL}
- {$DEFINE _HACK1}
- {$I MMHACK.INC}
- {$ENDIF}
- {$ENDIF}
- end;
- {-- TMMEnvelope ---------------------------------------------------------}
- { AddPoint f黦t einen Punkt in die Liste ein, AddPoint erzeugt eine Kopie}
- function TMMEnvelope.AddPoint(aPoint: TMMEnvelopePoint; Align: Boolean): Boolean;
- var
- i: integer;
- NewPoint: TMMEnvelopePoint;
- begin
- Result := False;
- if QueryPoint(aPoint) then { passt hier Punkt ueberhaupt hin ? }
- begin
- NewPoint := TMMEnvelopePoint.Create;
- NewPoint.Assign(aPoint);
- i := LocatePoint(NewPoint.X_Value);
- if (i < 1) or (i >= Count) then Points.AddObject(NewPoint)
- else
- begin
- { neuen Punkt genau auf Linie zwischen zwei Punken einf黦en }
- if Align then
- with NewPoint do
- begin
- { Stefans Dreisatz oder wei